go-micro启动
// 创建一个服务
service := micro.NewService(
micro.Name("go.micro.srv.hello"),
micro.Version("latest"),
micro.Registry(etcd.NewRegistry()),
)
func newService(opts ...Option) Service {
service := new(service)
options := newOptions(opts...)
// 忽略代码
// 创建客户端
options.Client = wrapper.FromService(serviceName, options.Client)
options.Client = wrapper.TraceCall(serviceName, trace.DefaultTracer, options.Client)
//忽略代码
// set opts
service.opts = options
return service
}
func newOptions(opts ...Option) Options {
//初始化组件
opt := Options{
Auth: auth.DefaultAuth,
Broker: broker.DefaultBroker,
Cmd: cmd.DefaultCmd,
Client: client.DefaultClient,
Server: server.DefaultServer,
Registry: registry.DefaultRegistry,
Transport: transport.DefaultTransport,
Context: context.Background(),
Signal: true,
}
//循环执行传入的组件 相当于上面的
//micro.Name("go.micro.srv.hello")
for _, o := range opts {
o(&opt)
}
return opt
}
上面的代码对配置进行了初始化,创建了服务对象
// 启动服务
if err := service.Run(); err != nil {
log.Fatal(err)
}
// 启动服务
func (s *service) Run() error {
// 忽略代码
log.Infof("Starting [service] %s", s.Name())
//启动服务
if err := s.Start(); err != nil {
return err
}
//注册信号量
ch := make(chan os.Signal, 1)
if s.opts.Signal {
signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT)
}
//监听信号量
select {
// wait on kill signal
case <-ch:
// wait on context cancel
case <-s.opts.Context.Done():
}
return s.Stop()
}
// 启动
func (s *service) Start() error {
//执行前缀钩子
for _, fn := range s.opts.BeforeStart {
if err := fn(); err != nil {
return err
}
}
//启动代码
if err := s.opts.Server.Start(); err != nil {
return err
}
//执行后缀钩子
for _, fn := range s.opts.AfterStart {
if err := fn(); err != nil {
return err
}
}
return nil
}
// 使用grpc提供的服务
func (g *grpcServer) Start() error {
//...忽略代码
//启动服务
if l := g.getListener(); l != nil {
ts = l
}
//...忽略代码
// 注册
if err := g.Register(); err != nil {
log.Errorf("Server register error: ", err)
}
//...忽略代码
//启动自动注册
Loop:
for {
select {
// register self on interval
case <-t.C:
if err := g.Register(); err != nil {
log.Error("Server register error: ", err)
}
// wait for exit
case ch = <-g.exit:
break Loop
}
}
// 忽略代码
return nil
}
// 注册服务
func (g *grpcServer) Register() error {
//...忽略环境判断等代码
addr, err := addr.Extract(host)
if err != nil {
return err
}
// make copy of metadata
md := make(meta.Metadata)
for k, v := range config.Metadata {
md[k] = v
}
// 生成注册服务
node := ®istry.Node{
Id: config.Name + "-" + config.Id,
Address: mnet.HostPort(addr, port),
Metadata: md,
}
node.Metadata["broker"] = config.Broker.String()
node.Metadata["registry"] = config.Registry.String()
node.Metadata["server"] = g.String()
node.Metadata["transport"] = g.String()
node.Metadata["protocol"] = "grpc"
g.RLock()
// 忽略代码
service := ®istry.Service{
Name: config.Name,
Version: config.Version,
Nodes: []*registry.Node{node},
Endpoints: endpoints,
}
g.Lock()
registered := g.registered
g.Unlock()
if !registered {
log.Infof("Registry [%s] Registering node: %s", config.Registry.String(), node.Id)
}
// 创建注册服务灿鸟叔
rOpts := []registry.RegisterOption{registry.RegisterTTL(config.RegisterTTL)}
//真正的注册调用
if err := config.Registry.Register(service, rOpts...); err != nil {
return err
}
// ...忽略代码
}
生成各种服务代码参数,检测服务环境,最后组装成服务变量,传递给服务
type Registry interface {
Init(...Option) error
Options() Options
Register(*Service, ...RegisterOption) error
Deregister(*Service) error
GetService(string) ([]*Service, error)
ListServices() ([]*Service, error)
Watch(...WatchOption) (Watcher, error)
String() string
}
只要实现了上面的Registry接口,都可以成为micro的注册服务,这种基于接口的方式,可以让注册服务随意切换
使用memory这种简单的注册服务,了解下注册服务的相关逻辑
func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption) error {
// 循环参数
for _, o := range opts {
o(&options)
}
// 获取监听对象
r := serviceToRecord(s, options.TTL)
// 如果不存在就创建这个变量
if _, ok := m.records[s.Name]; !ok {
m.records[s.Name] = make(map[string]*record)
}
//如果是第一次的话 启动go m.sendEvent协程
if _, ok := m.records[s.Name][s.Version]; !ok {
m.records[s.Name][s.Version] = r
log.Debugf("Registry added new service: %s, version: %s", s.Name, s.Version)
go m.sendEvent(®istry.Result{Action: "update", Service: s})
return nil
}
// 忽略代码
return nil
}
func (m *Registry) sendEvent(r *registry.Result) {
m.RLock()
watchers := make([]*Watcher, 0, len(m.watchers))
for _, w := range m.watchers {
watchers = append(watchers, w)
}
m.RUnlock()
// 监听变量,如果服务退出就取消
for _, w := range watchers {
select {
case <-w.exit:
m.Lock()
delete(m.watchers, w.id)
m.Unlock()
default:
select {
case w.res <- r:
case <-time.After(sendEventTime):
}
}
}
}
```go
上面分析了服务注册的代码,当服务生成的时候,将服务的信息组合好,传到基于实现Registry的对象中,将服务注册到服务发现服务中,貌似这里面没有服务非主动掉线,心跳检测的代码,后面再慢慢看
> 服务已经注册上了,接下来就是客户端怎么调用的问题了