1 服务初始化
1.1 服务接口
go-micro将微服务需要的功能做了抽象,定义了Service接口
// Service is an interface that wraps the lower level libraries
// within go-micro. Its a convenience method for building
// and initialising services.
type Service interface {
Init(...Option) //初始化微服务
Options() Options //返回微服务选项
Client() client.Client //返回微服务客户端
Server() server.Server //返回微服务服务端
Run() error //运行微服务
String() string //返回微服务名字
}
如果需要,我们可以自己实现Service,而不是必须调用micro.NewService来初始化我们的服务;我们先看下go-micro实现的Service。
首先是new出一个服务
//初始化服务
service := micro.NewService(
micro.Name("go.micro.srv.foo"),
micro.Version("latest"),
)
NewService 函数实现和Service接口同样在github.com/micro/go-micro/micro.go,
// NewService creates and returns a new Service based on the packages within.
func NewService(opts ...Option) Service {
return newService(opts...)
}
进而调用github.com/micro/go-micro/service.go里面的newService
type service struct {
opts Options
once sync.Once
}
func newService(opts ...Option) Service {
//Options是Service的组件实现,这里用传入的参数初始化默认组件
options := newOptions(opts...)
options.Client = &clientWrapper{
options.Client,
metadata.Metadata{
HeaderPrefix + "From-Service": options.Server.Options().Name,
},
}
//构造Service实现实例
return &service{
opts: options,
}
}
这个文件的代码都是go-micro对Service接口的实现,包含Init(),Options(), Client(), Server(), Run() 的接口函数的实现,我们先看下如何构造Service实例的,首先是用选项参数初始化默认服务组件
func newOptions(opts ...Option) Options {
//这里是Service各个组件的默认实现
opt := Options{
Broker: broker.DefaultBroker,
Cmd: cmd.DefaultCmd,
Client: client.DefaultClient,
Server: server.DefaultServer,
Registry: registry.DefaultRegistry,
Transport: transport.DefaultTransport,
Context: context.Background(),
}
//用传入参数初始化默认组件
for _, o := range opts {
o(&opt)
}
return opt
}
如我们传入Name和Version选项参数:
// Name of the service
func Name(n string) Option {
return func(o *Options) {
o.Server.Init(server.Name(n))
}
}
// Version of the service
func Version(v string) Option {
return func(o *Options) {
o.Server.Init(server.Version(v))
}
}
到最后,都是调用Server的Init函数完成默认组件初始化。
1.2 参数解析和服务初始化
//设置默认选项,解析参数等
service.Init()
看下具体实现
// Init initialises options. Additionally it calls cmd.Init
// which parses command line flags. cmd.Init is only called
// on first Init.
func (s *service) Init(opts ...Option) {
// process options
//如果传入,会覆盖原来的选项参数
for _, o := range opts {
o(&s.opts)
}
s.once.Do(func() {
// Initialise the command flags, overriding new service
//参数解析,
_ = s.opts.Cmd.Init(
cmd.Broker(&s.opts.Broker),
cmd.Registry(&s.opts.Registry),
cmd.Transport(&s.opts.Transport),
cmd.Client(&s.opts.Client),
cmd.Server(&s.opts.Server),
)
})
}
s.opts.Cmd就是DefaultCmd
var (
DefaultCmd = newCmd()
DefaultFlags = []cli.Flag{
cli.StringFlag{
Name: "client",
EnvVar: "MICRO_CLIENT",
Usage: "Client for go-micro; rpc",
},
cli.StringFlag{
Name: "client_request_timeout",
EnvVar: "MICRO_CLIENT_REQUEST_TIMEOUT",
Usage: "Sets the client request timeout. e.g 500ms, 5s, 1m. Default: 5s",
},
cli.IntFlag{
Name: "client_retries",
EnvVar: "MICRO_CLIENT_RETRIES",
Usage: "Sets the client retries. Default: 1",
},
cli.IntFlag{
Name: "client_pool_size",
EnvVar: "MICRO_CLIENT_POOL_SIZE",
Usage: "Sets the client connection pool size. Default: 1",
},
cli.StringFlag{
Name: "client_pool_ttl",
EnvVar: "MICRO_CLIENT_POOL_TTL",
Usage: "Sets the client connection pool ttl. e.g 500ms, 5s, 1m. Default: 1m",
},
cli.IntFlag{
Name: "register_ttl",
EnvVar: "MICRO_REGISTER_TTL",
Usage: "Register TTL in seconds",
},
cli.IntFlag{
Name: "register_interval",
EnvVar: "MICRO_REGISTER_INTERVAL",
Usage: "Register interval in seconds",
},
cli.StringFlag{
Name: "server",
EnvVar: "MICRO_SERVER",
Usage: "Server for go-micro; rpc",
},
cli.StringFlag{
Name: "server_name",
EnvVar: "MICRO_SERVER_NAME",
Usage: "Name of the server. go.micro.srv.example",
},
cli.StringFlag{
Name: "server_version",
EnvVar: "MICRO_SERVER_VERSION",
Usage: "Version of the server. 1.1.0",
},
cli.StringFlag{
Name: "server_id",
EnvVar: "MICRO_SERVER_ID",
Usage: "Id of the server. Auto-generated if not specified",
},
cli.StringFlag{
Name: "server_address",
EnvVar: "MICRO_SERVER_ADDRESS",
Usage: "Bind address for the server. 127.0.0.1:8080",
},
cli.StringFlag{
Name: "server_advertise",
EnvVar: "MICRO_SERVER_ADVERTISE",
Usage: "Used instead of the server_address when registering with discovery. 127.0.0.1:8080",
},
cli.StringSliceFlag{
Name: "server_metadata",
EnvVar: "MICRO_SERVER_METADATA",
Value: &cli.StringSlice{},
Usage: "A list of key-value pairs defining metadata. version=1.0.0",
},
cli.StringFlag{
Name: "broker",
EnvVar: "MICRO_BROKER",
Usage: "Broker for pub/sub. http, nats, rabbitmq",
},
cli.StringFlag{
Name: "broker_address",
EnvVar: "MICRO_BROKER_ADDRESS",
Usage: "Comma-separated list of broker addresses",
},
cli.StringFlag{
Name: "registry",
EnvVar: "MICRO_REGISTRY",
Usage: "Registry for discovery. consul, mdns",
},
cli.StringFlag{
Name: "registry_address",
EnvVar: "MICRO_REGISTRY_ADDRESS",
Usage: "Comma-separated list of registry addresses",
},
cli.StringFlag{
Name: "selector",
EnvVar: "MICRO_SELECTOR",
Usage: "Selector used to pick nodes for querying",
},
cli.StringFlag{
Name: "transport",
EnvVar: "MICRO_TRANSPORT",
Usage: "Transport mechanism used; http",
},
cli.StringFlag{
Name: "transport_address",
EnvVar: "MICRO_TRANSPORT_ADDRESS",
Usage: "Comma-separated list of transport addresses",
},
}
DefaultBrokers = map[string]func(...broker.Option) broker.Broker{
"http": http.NewBroker,
"memory": memory.NewBroker,
}
DefaultClients = map[string]func(...client.Option) client.Client{
"rpc": client.NewClient,
}
DefaultRegistries = map[string]func(...registry.Option) registry.Registry{
"consul": consul.NewRegistry,
"gossip": gossip.NewRegistry,
"mdns": mdns.NewRegistry,
"memory": rmem.NewRegistry,
}
DefaultSelectors = map[string]func(...selector.Option) selector.Selector{
"default": selector.NewSelector,
"dns": dns.NewSelector,
"cache": selector.NewSelector,
"static": static.NewSelector,
}
DefaultServers = map[string]func(...server.Option) server.Server{
"rpc": server.NewServer,
}
DefaultTransports = map[string]func(...transport.Option) transport.Transport{
"memory": tmem.NewTransport,
"http": thttp.NewTransport,
}
// used for default selection as the fall back
defaultClient = "rpc"
defaultServer = "rpc"
defaultBroker = "http"
defaultRegistry = "mdns"
defaultSelector = "registry"
defaultTransport = "http"
如,我们传入go run client.go --registry=consul,服务注册发现将解析为consul.NewRegistry,而默认情况下是是mdns
DefaultRegistries = map[string]func(...registry.Option) registry.Registry{
"consul": consul.NewRegistry,
"gossip": gossip.NewRegistry,
"mdns": mdns.NewRegistry,
"memory": rmem.NewRegistry,
}
func newRegistry(opts ...Option) Registry {
options := Options{
Timeout: time.Millisecond * 100,
}
return &mdnsRegistry{
opts: options,
services: make(map[string][]*mdnsEntry),
}
}