( micro/go-micro 本系列,是根据代码阅读顺序,边看边写,因此暂缺一篇工程目录文件综合性的介绍,最后补上)
Option 机制
micro/go-micro 代码中,可以通过 Option 来显式配置微服务属性,来达成:
- 初始化微服务设置
- 添加微服务某些功能(通过 Option 来传递 middleware )
- 替换微服务某些功能(通过 Option 来替换插件)
具体例子,感性认识下:
func main() {
service := micro.NewService(
micro.Name("greeter"), // 这是个 Option 对象,设置微服务名称
micro.WrapHandler(logWrapper), // 这是个 Option 对象,添加一个自定义 log 中间件
micro.Registry(kubernetes.NewRegistry()), // 这是个 Option 对象,替换`服务发现`插件为 kubernetes
)
service.Init()
if err := service.Run(); err != nil {
fmt.Println(err)
}
}
关于 Option 的实现细节,请参考: Golang 编程之装饰器模式
命令行参数
micro/go-micro 中,命令行参数是 Option 机制的补充,以方便在启动程序时,来配置微服务属性
micro/go-micro 中,命令行参数相关功能流程:
- 初始化默认值
- 解析命令行参数
- 根据命令行参数,更新 Option 设置
下面代码分析解读下
0. 相关 Option 对象
摘自: https://github.com/micro/go-micro/blob/master/config/cmd/options.go , 并添加注释
type Options struct {
// For the Command Line itself
Name string // Option Name 最终作用于这个字段
Description string // Option Description 最终作用于这个字段
Version string // Option Version 最终作用于这个字段
// We need pointers to things so we can swap them out if needed.
Broker *broker.Broker // Option Broker 最终作用于这个字段
Registry *registry.Registry // Option Registry 最终作用于这个字段
Selector *selector.Selector // Option Selector 最终作用于这个字段
Transport *transport.Transport // Option Transport 最终作用于这个字段
Client *client.Client // Option Client 最终作用于这个字段
Server *server.Server // Option Server 最终作用于这个字段
// 所有插件列表
Brokers map[string]func(...broker.Option) broker.Broker
Clients map[string]func(...client.Option) client.Client
Registries map[string]func(...registry.Option) registry.Registry
Selectors map[string]func(...selector.Option) selector.Selector
Servers map[string]func(...server.Option) server.Server
Transports map[string]func(...transport.Option) transport.Transport
// Other options for implementations of the interface
// can be stored in a context
Context context.Context // 插件开发等第 3 方 Option 可以用这个存
}
// 下面是选项,需要注意,一些选项会对应多个命令行参数
// Command line Name
func Name(n string) Option {
return func(o *Options) {
o.Name = n
}
}
// 类似`创建选项`代码 略
1. 初始化默认值
摘自: https://github.com/micro/go-micro/blob/master/config/cmd/cmd.go , 并添加注释
var (
DefaultCmd = newCmd()
// 设置命令行参数
DefaultFlags = []cli.Flag{
cli.StringFlag{
Name: "client",
EnvVar: "MICRO_CLIENT",
Usage: "Client for go-micro; rpc",
},
// 类似命令行参数初始化代码 略
}
// 初始化内置插件列表
DefaultBrokers = map[string]func(...broker.Option) broker.Broker{
"http": http.NewBroker,
"memory": memory.NewBroker,
"nats": nats.NewBroker,
}
// 类似内置插件列表初始化代码 略
)
根据代码,汇总下目前所有命令行参数:
命令行参数 | 说明 |
---|---|
client | client 插件名称 |
client_request_timeout | client 请求超时时间,缺省 5 秒 |
client_retries | client 请求重试次数,缺省 1 次(某些服务发现插件,强调服务可用性,因此存在旧数据,会有可能导致把请求发至不可用的微服务实例上) |
client_pool_size | client 连接池大小,缺省 1 个连接 |
client_pool_ttl | client 连接池中连接存活时间,缺省 1 分钟 |
register_ttl | 服务发现组件中的节点存活时间 |
register_interval | 服务发现组件中的节点多久刷新自己,来避免自己被 register_ttl 掉 |
server | server 插件名称 |
server_name | 微服务名 |
server_version | 微服务版本号 |
server_id | 微服务节点的节点ID。如果没设置, micro/go-micro 自动设置为 UUID |
server_address | 微服务服务地址。格式比如: 127.0.0.1:8080 |
server_advertise | 微服务上报服务发现组件时,用的地址 |
server_metadata | 微服务自身元数据,会上报给服务发现组件。是一个 key-value 列表,比如: --server_metadata color=red --server_metadata dc=sh |
broker | broker 插件名称 |
broker_address | broker 服务器地址列表。比如: 127.0.0.1:8000,127.0.0.1:8001,127.0.0.1:8002 |
registry | registry 插件名称 |
registry_address | registry 服务器地址列表。比如: 127.0.0.1:8000,127.0.0.1:8001,127.0.0.1:8002 |
selector | selector 插件名称 |
transport | transport 插件名称 |
transport_address | 目前代码中未用到该命令行参数! |
根据代码,汇总下目前所有内置插件列表如下:
模块 | 内置插件列表 | 默认插件 |
---|---|---|
client | rpc 、 mucp 、 grpc | rpc |
server | rpc 、 mucp 、 grpc | rpc |
broker | http 、 memory 、 nats | http |
registry | consul 、 gossip 、 mdns 、 memory | mdns |
selector | default 、 dns 、 cache 、 static | default( registry ) |
transport | memory 、 http 、 grpc | http |
注意: codec 模块,未设置对应的命令行参数;不同的 client 、 server 模块,它们的默认codec 模块实现都可能不一样,因此,没有对应的命令行参数
2. 解析命令行参数
摘自: https://github.com/micro/go-micro/blob/master/config/cmd/cmd.go
func (c *cmd) Init(opts ...Option) error {
for _, o := range opts {
o(&c.opts)
}
c.app.Name = c.opts.Name
c.app.Version = c.opts.Version
c.app.HideVersion = len(c.opts.Version) == 0
c.app.Usage = c.opts.Description
c.app.RunAndExitOnError()
return nil
}
micro/go-micro 使用了 micro/cli 库做命令行解析,这块细节可以跳过
3. 根据命令行参数,更新 Option 设置
摘自: https://github.com/micro/go-micro/blob/master/config/cmd/cmd.go
func (c *cmd) Before(ctx *cli.Context) error {
// 代码略
}
一看就懂,细节略
其他
micro/go-micro 插件的可插拔机制,就是通过命令行参数来实现的
具体运用以下相关内容:
- 命令行参数
- 包导入自动注册
- 工厂模式
细节请参考: Golang 编程之工厂模式
以上