暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

云原生 | go-micro@v4.9.0源码阅读

689





Cloud Native

ESG服务BU云原生交付中心、云基地

在云原生上的尝试、调研与分享




本期内容 

 go-micro@v4.9.0

源码阅读 



Go是一款开源的编程语言,能更容易地构造简单、可靠且高效的软件,具备高并发,静态编译等特性,在性能、安全等方面具备非常大的优势。


而go-micro则是基于Go的微服务编程框架,操作简单、编码高效、功能强大。想进一步了解go-micro,请查看我们的往期文章:go-micro学习与实践


本文章基于基于go-micro@v4.9.0版本,内容全面详实,预计阅读时长10分钟,建议先收藏! 那么下面就让我们开启go-micro源码阅读之旅吧!





创建微服务  


使⽤官⽹提供的cli插件直接创建⼀个微服务。


 插件下载:

go install 

github.com/go-micro/cli/cmd/go-micro@latest


 创建微服务 go-micro new service helloworld

 依赖更新及下载 make init proto update tidy



微服务创建成功后,微服务包含以下⼏个⽬录结构:





源码阅读 


下面我们先从微服务的启动入口 main.go 开始分析起。


main.go

    func main() {
    // 组件配置
    srv := micro.NewService(
    //micro.Name(service),
    //micro.Version(version),
    micro.Server(server.DefaultServer),
    micro.Client(client.DefaultClient),
    micro.Broker(broker.DefaultBroker),
    micro.Registry(registry.DefaultRegistry),
    micro.Transport(transport.DefaultTransport),
    micro.Auth(auth.DefaultAuth),
    micro.Cache(cache.DefaultCache),
    micro.Cmd(cmd.DefaultCmd),
    micro.Config(config.DefaultConfig),
    micro.Runtime(runtime.DefaultRuntime),main进⾏了三个操作:组件配置,注册服务处理,启动微服务
    注册服务处理
    proto:定义服务
    helloworld.proto:protobuf格式的协议定义服务
    上述定义了⼀个服务Helloworld,该服务包含4个⽅法:Call, ClientStream, ServerStream, BidiStream
    helloworld.pb.go:由protoc --go_out=:. proto/helloworld.proto⽣成。该⽂件会包含⽅法⼊参,出参的结构体及
    对应的编码规范。
    helloworld.pb.micro.go:由protoc --micro_out=. proto/hellloworld.proto⽣成。该⽂件会包含
    HelloworldHandler接⼝(该接⼝包含了4个服务⽅法),及该接⼝注册到微服务的RegisterHelloworldHandler。
    handler:微服务的具体处理逻辑
    helloworld.go:实现helloworld.pb.micro.go中定义的HelloworldHandler接⼝。
    注册流程,详⻅核⼼组件server.Server组件讲解;调⽤流程,详⻅client.Client组件讲解。
    组件配置
    micro.Profile(profile.DefaultProfile),
    micro.Store(store.DefaultStore),
    micro.Logger(logger.DefaultLogger),
    )
    srv.Init()
    // 注册服务处理
    pb.RegisterHelloworldHandler(srv.Server(), new(handler.Helloworld))
    // 启动微服务
    if err := srv.Run(); err != nil {
    log.Fatal(err)
    }
    }




    可以看到,main进⾏了三个操作:


    • 注册服务处理

    • 组件配置

    • 启动微服务


    下面我们逐个来看这三个操作。




    操作一:注册服务处理  


     proto:定义服务 


    helloworld.proto: protobuf格式的协议定义服务


      service Helloworld {
      rpc Call(CallRequest) returns (CallResponse) {}
      rpc ClientStream(stream ClientStreamRequest) returns (ClientStreamResponse) {}
      rpc ServerStream(ServerStreamRequest) returns (stream ServerStreamResponse) {}
      rpc BidiStream(stream BidiStreamRequest) returns (stream BidiStreamResponse) {}
      }



      上述定义了⼀个服务Helloworld,该服务包含4个⽅法:Call, ClientStream, ServerStream, BidiStream。

      helloworld.pb.go

      由protoc --go_out=:. proto/helloworld.proto⽣成。该⽂件会包含⽅法⼊参,出参的结构体及对应的编码规范。

      helloworld.pb.micro.go

      由protoc --micro_out=. proto/hellloworld

      .proto⽣成。


      该⽂件会包含HelloworldHandler接⼝(该接⼝包含了4个服务⽅法),及该接⼝注册到微服务的RegisterHelloworldHandler。



       handler:微服务的具体处理逻辑 


      helloworld.go

      实现helloworld.pb.micro.go中定义的HelloworldHandler接⼝。


      注册流程,详⻅核⼼组件server.Server组件讲解;调⽤流程,详⻅client.Client组件讲解。





      操作二:组件配置   



       顶层结构 


      micro.Service


      微服务的顶层抽象。⽤于定义微服务的服务信息及控制着整个微服务⽣命周期。包含以下⼏个⽅法。


        type Service interface {
        // The service name
        Name() string
        // Init initialises options
        Init(...Option)
        // Options returns the current options
        Options() Options
        // Client is used to call services
        Client() client.Client
        // Server is for handling requests and events
        Server() server.Server
        // Run the service
        Run() error
        // The service implementation
        String() string
        }



        默认实现的结构体为micro.service


          type service struct {
          opts Options
          once sync.Once
          }


          opts Options 是微服务的配置项,包含该微服务⽤到的其他组件,⽣命周期执⾏钩⼦函数(服务启动前执⾏钩⼦函数,服务关闭前执⾏的钩⼦函数,服务启动后执⾏的钩⼦函数,服务关闭后执⾏的钩⼦函数),服务上下⽂,是否启⽤系统信号关闭服务的配置项。


          once sync.Once 保证只执⾏⼀次加载启动参数。



           核心组件 


          核⼼组件是构成微服务的必要组件。


          server.Server

          微服务的服务端


            type Server interface {
            // Initialise options
            Init(...Option) error
            // Retrieve the options
            Options() Options
            // Register a handler
            Handle(Handler) error
            // Create a new handler
            NewHandler(interface{}, ...HandlerOption) Handler
            // Create a new subscriber
            NewSubscriber(string, interface{}, ...SubscriberOption) Subscriber
            // Register a subscriber
            Subscribe(Subscriber) error
            // Start the server
            Start() error
            // Stop the server
            Stop() error
            // Server implementation
            String() string
            }


            以mucp的实现为例。实现组件的结构体为server.rpcServer


              type rpcServer struct {
              router *router
              exit chan chan error
              sync.RWMutex
              opts Options
              handlers map[string]Handler
              subscribers map[Subscriber][]broker.Subscriber
              // marks the serve as started
              started bool
              // used for first registration
              registered bool
              // subscribe to service name
              subscriber broker.Subscriber
              // graceful exit
              wg *sync.WaitGroup
              rsvc *registry.Service
              }





              rpcServer 包含以下⼏种信息:


              #1

              服务处理


              rpcServer有两种服务处理:


              ⼀种是表示服务请求的rpcHandler

              ⼀种是表示消息处理的subscriber


              rpcHandler:⼀个微服务可定义多个rpc服务,每个rpc服务对应⼀个的rpcHandler,通过map的形式保存在rpcServer中。


              通过NewHandler⽅法⽣成, handler为⼀个⾃定义的结构体,该结构体对应rpc服务名,结构体上的外部⽅法对应rpc服务⽅法。


              subscriber:⼀个微服务可订阅多个消息,每个消息对应⼀个subscriber,通过map的形式保存在rpcServer中。


              通过NewSubscriber⽅法⽣成,参数topic表示订阅的消息;参数sub是⼀个⽅法,⽅法签名为:

              "func(context.Context, interface{}) error"

              表示该消息的处理逻辑。



              #2

              路由


              构建路由信息



              绑定服务:⽤户将服务注册到框架中。rpcServer针对两种请求类型有不同的绑定⽅法。



              解析服务:解析路由信息,解析服务处理信息存储到router中。


              服务注册:将服务信息,节点信息,路由信息,发送到服务注册中⼼进⾏注册。



              使⽤路由信息


              接收消息:从注册中⼼或消息中⼼,接收到需要处理的请求。


              统⼀拦截:接受到请求后,执⾏中间件中的函数,先配置的先执⾏。


              端点分发:根据请求端点,匹配到分发器中的对应处理⽅法的放射类型。


              请求解码:根据content-type,对请求体进⾏解码,得到⽅法的⼊参。


              服务处理:使⽤⼊参,执⾏反射⽅法。


              rpcServer的router路由中存储着两种不同类型的路由。



              #3

              配置


              rpcServer包含多种配置信息:

              节点信息配置:包含服务id,服务名称,监听地址,节点元数据,上下⽂等。

              组件配置:包含注册中⼼,消息中⼼,服务通信,编码器等

              拦截器配置:包含服务请求拦截器,消息通知拦截器。


              #4

              状态信息


              rpcServer的状态信息包含:服务运⾏状态,注册状态,退出执⾏状态等。


              client.Client

              微服务的客户端


                type Client interface {
                Init(...Option) error
                Options() Options
                NewMessage(topic string, msg interface{}, opts ...MessageOption) Message // 构建消息
                NewRequest(service, endpoint string, req interface{}, reqOpts ...RequestOption)
                Request // 构建服务请求
                Call(ctx context.Context, req Request, rsp interface{}, opts ...CallOption) error //
                调⽤服务端
                Stream(ctx context.Context, req Request, opts ...CallOption) (Stream, error) // 构建
                双向通信
                Publish(ctx context.Context, msg Message, opts ...PublishOption) error // 发布消息
                String() string
                }


                以mucp的实现为例。实现组件的结构体为client.rpcClient


                  type rpcClient struct {
                  seq uint64
                  once atomic.Value
                  opts Options
                  pool pool.Pool
                  }


                  rpcClient 包含以下⼏种信息:


                  #1

                  请求链



                  构建请求 rpcClient针对两种不同的请求类型,有不同构建⽅法。



                  请求备份:发起请求后,通过BackoffFunc函数对请求进⾏备份,备份时,会阻塞请求。rpcClient没有默认的请求备份,⽀持⾃定义配置BackoffFunc函数。


                  选择节点:从注册中⼼获取请求⽬标服务对应的所有节点。通过Selector选择器选取节点, rpcClient默认使⽤随机算法来选取节点,⽀持⾃定义选择器。


                  中间件:选取节点后,执⾏中间件函数。先配置的先执⾏。


                  发送请求:

                  • 选择好的服务节点建⽴连接,连接建⽴成功后,将连接放⼊连接池,请求重试时,后续相同的请求可以直接在连接池中获取

                  • 使⽤编码器对请求编码,发送请求数据


                  解析响应:获取响应后,使⽤解码器对响应解码并依次返回到最上层⽅法。



                  #2

                  配置


                  组件配置:消息中⼼,编码/解码器,注册中⼼,节点选择器,通信⽅式等。


                  请求配置:连接池,中间件,超时时间等。



                   核心组件衍生 


                  broker.Broker

                  消息组件,⽤于与消息中⼼交互。


                    type Broker interface {
                    Init(...Option) error
                    Options() Options
                    Address() string
                    Connect() error
                    Disconnect() error
                    Publish(topic string, m *Message, opts ...PublishOption) error
                    Subscribe(topic string, h Handler, opts ...SubscribeOption) (Subscriber, error)
                    String() string
                    }


                    / 组件基本逻辑


                    以http实现为例。 http是go-micro默认组件实现,具体的结构体为broker.HttpBroker


                      type httpBroker struct {
                      id string
                      address string
                      opts Options
                      mux *http.ServeMux
                      c *http.Client
                      r registry.Registry
                      sync.RWMutex
                      subscribers map[string][]*httpSubscriber
                      running bool
                      exit chan chan error
                      // offline message inbox
                      mtx sync.RWMutex
                      inbox map[string][][]byte
                      }



                      httpBroker 包含以下⼏种信息:


                      #1

                      发布消息


                      httpBroker通过Publish⽅法发布消息。


                      消息编码:httpBroker默认使⽤json进⾏消息编码。编码完的消息缓存到inbox字段中。


                      获取订阅端:每个订阅端节点,都会以微服务的形式将订阅信息注册到服务注册中⼼。不同于其他⾃定义的微服务,订阅端微服务的名称为固定值:micro.http.broker。


                      (当⼀个节点有订阅消息时,会注册两个微服务信息,⼀个是⾃身service定义的微服务,⼀个是固定的消息订阅微服务)。


                      httpBroker先通过微服务名(micro.http.broker)获取所有的订阅端节点信息,然后通过topic过滤得到对应消息订阅端的节点列表。


                      发送http请求:httpBroker通过节点选取规则选择节点,从inbox中取出消息,并向这些节点发送http请求。


                      httpBroker有两种选取规则。通过broker.Queue()进⾏设置。




                      #2

                      订阅消息


                      httpBroker通过Subscribe⽅法订阅消息:



                      注册订阅微服务:httpBroker构建微服务信息,并注册到注册中⼼。


                      微服务信息包含:服务名(固定值:
                      micro.http.broker),消息topic,处理函数,当前节点信息等。



                      #3

                      配置


                      httpBroker可配置的信息有: broker相关信息(地址, tls连接,上下⽂等), registry相关信息,编码器等



                      #4

                      状态信息


                      httpBroker有两种状态:


                      ⼀种是连接状态,⼀种是断开状态。


                      registry.Registry


                      服务注册中⼼组件,⽤于与注册中⼼交互。服务注册中⼼存储所有的服务节点信息,以便于其他节点能够获取。


                        type Registry interface {
                        Init(...Option) error
                        Options() Options
                        Register(*Service, ...RegisterOption) error
                        Deregister(*Service, ...DeregisterOption) error
                        GetService(string, ...GetOption) ([]*Service, error)
                        ListServices(...ListOption) ([]*Service, error)
                        Watch(...WatchOption) (Watcher, error)
                        String() string
                        }


                        / 组件基本逻辑


                        以etcd实现为例。etcd实现不是go-micro的默认实现,需要引⼊go-micro组件库。etcd实现的结构体为etcd.etcdRegistry。


                          type etcdRegistry struct {
                          client *clientv3.Client
                          options registry.Options
                          sync.RWMutex
                          register map[string]uint64
                          leases map[string]clientv3.LeaseID
                          }


                          etcdRegistry 包含以下信息:


                          #1

                          注册


                          etcdRegistry通过etcd的api进⾏注册、续约、删除等操作。


                          etcdRegistry包含两个注册相关数据:


                          • register map[string]uint64:存储已注册节点的hash值,当该节点再次发起注册时,对⽐节点信息是否有更改。

                          • leases map[string]clientv3.LeaseID:存储已注册节点的LeaseID,当该节点再次发起注册时(注册⼼跳维持场景),进⾏注册续约。



                          #2

                          配置


                          配置信息包含registry连接配置(地址, ttl, tls,上下⽂等), etcd连接客户端。



                          transport.Transport


                          微服务调⽤组件。定义服务间通信⽅式。


                          / 组件基本逻辑


                          以http实现为例。transport.httpTransport是go-micro的默认实现。


                            type httpTransport struct {
                            opts Options
                            }


                            httpTransport 包含以下信息:


                            #1

                            监听



                            端⼝监听:启动tcp端⼝监听。返回监听器httpTransportListener。


                            建⽴连接⼀个微服务可订阅多个消息,每个消息对应⼀个subscriber,通过map的形式保存在rpcServer中。



                            #2

                            请求



                            创建连接:创建tcp连接到服务端。返回客户端httpTransportClient。


                            发送数据:通过Send⽅法,将请求写⼊到连接中。


                            接收数据:通过Recv⽅法,从连接中读取响应。



                            #3

                            配置


                            配置包含:连接地址, tls, ttl,上下⽂等。




                             功能组件 


                            功能组件在核⼼流程中并未使⽤。应根据需要⾃⾏使⽤。


                            auth.Auth

                            认证组件


                              type Auth interface {
                              // Init the auth
                              Init(opts ...Option)
                              // Options set for auth
                              Options() Options
                              // Generate a new account
                              Generate(id string, opts ...GenerateOption) (*Account, error)
                              // Inspect a token
                              Inspect(token string) (*Account, error)
                              // Token generated using refresh token or credentials
                              Token(opts ...TokenOption) (*Token, error)
                              // String returns the name of the implementation
                              String() string
                              }


                              / 组件基本逻辑


                              以jwt实现为例。go-micro默认没有实现。组件库中jwt实现的结构体为jwt.jwt


                                type jwt struct {
                                sync.Mutex
                                options auth.Options
                                jwt jwtToken.Provider
                                }


                                jwt 包含以下⼏种信息:


                                #1

                                token⽣成器



                                组装账号信息:通过Generate⽅法⽣成账号信息,账号信息包含⽤户id, secret(由jwt⽣成器⽣成,⽤于传递到token解析),⾃定义信息等。


                                ⽣成token:通过账号的secret解析出完整的账号信息(secret时效为15min,超时⽆法头盖⻣secret解析账号信息)。


                                然后再通过jwt⽣成器,对账号信息进⾏加密,⽣成具有指定时效的accesstoken和refreshtoken(refreshtoken的时效⽐accesstoken的⻓1h)。


                                解析token:从token值(accesstoken或refreshtoken)中解析出账号信息,超时的⽆法解析。



                                #2

                                配置


                                包含的配置信息有: jwt⽣成器配置(jwt公钥,私钥, token有效时间等),账号信息配置(⾃定义信息等)

                                cache.Cache

                                缓存组件


                                  type Cache interface {
                                  // Get gets a cached value by key.
                                  Get(ctx context.Context, key string) (interface{}, time.Time, error)
                                  // Put stores a key-value pair into cache.
                                  Put(ctx context.Context, key string, val interface{}, d time.Duration) error
                                  // Delete removes a key from cache.
                                  Delete(ctx context.Context, key string) error
                                  // String returns the name of the implementation.
                                  String() string
                                  }


                                  / 组件基本逻辑


                                  以redis实现为例。go-micro的缓存是key-value格式,默认memory实现, redis的实现结构体为redis.redisCache


                                    type redisCache struct {
                                    opts cache.Options
                                    client redis.UniversalClient
                                    }


                                    redisCache 包含以下⼏种信息:


                                    #1

                                    redis客户端


                                    ⽤于和redis进⾏交互。



                                    #2

                                    配置


                                    配置信息包含:缓存有效时间,缓存服务器地址,上下⽂等。

                                    cmd.Cmd

                                    命令⾏组件,用于定义参数等


                                      type Cmd interface {
                                      // The cli app within this cmd
                                      App() *cli.App
                                      // Adds options, parses flags and initialise
                                      // exits on error
                                      Init(opts ...Option) error
                                      // Options set within this command
                                      Options() Options
                                      }


                                      go-micro的默认实现为cmd.cmd


                                        type cmd struct {
                                        opts Options
                                        app *cli.App
                                        }


                                        cmd通过urfave/cli实现参数的设置与读取



                                        设置参数:通过设置cli.App的Flags进⾏参数设置。Flags包含参数类型,命令⾏参数名称,环境变量(多个值),参数说明,默认值等。


                                        解析参数:cli.App会将参数写⼊到cli.Context中,然后通过设置cli.App的Action进⾏参数的解析。

                                        config.Config

                                        配置组件,与配置中⼼交互


                                          type Config interface {
                                          // provide the reader.Values interface
                                          reader.Values
                                          // Init the config
                                          Init(opts ...Option) error
                                          // Options in the config
                                          Options() Options
                                          // Stop the config loader/watcher
                                          Close() error
                                          // Load config sources
                                          Load(source ...source.Source) error
                                          // Force a source changeset sync
                                          Sync() error
                                          // Watch a value for changes
                                          Watch(path ...string) (Watcher, error)
                                          }


                                          go-micro的默认实现为config.config


                                            type config struct {
                                            exit chan bool
                                            opts Options
                                            sync.RWMutex
                                            // the current snapshot
                                            snap *loader.Snapshot
                                            // the current values
                                            vals reader.Values
                                            }


                                            命令⾏组件,用于定义参数等



                                            config 包含以下⼏种信息:


                                            #1

                                            获取数据


                                            config通过Load⽅法或Sync⽅法,从数据源获取数据。获取到数据后,⽣成数据快照。



                                            #2

                                            监听数据


                                            连接到数据源后, config每隔1s从数据源同步数据,监控配置中⼼数据是否发⽣变化,当数据变动时,重新⽣成新的快照数据。



                                            #3

                                            成快照


                                            数据快照由两个部分构成:

                                            • 配置数据:从配置中⼼读取到的数据

                                            • 版本:⽣成快照的时间戳,保证缓存的快照都是最新的。



                                            #4

                                            读取数据


                                            go-micro的配置数据会解析为json格式


                                            获取:通过path获取对于值


                                            删除/更新:只能操作本地的内存数据,配置中⼼的数据不会发⽣变化

                                            runtime.Runtime

                                            服务管理组件。可⽤于管理其他微服务


                                              type Runtime interface {
                                              // Init initializes runtime
                                              Init(...Option) error
                                              // Create registers a service
                                              Create(*Service, ...CreateOption) error
                                              // Read returns the service
                                              Read(...ReadOption) ([]*Service, error)
                                              // Update the service in place以kubernetes实现为例。go-micro的默认实现为runtime.runtime,只适⽤于所有服务在同⼀个操作系统中的场
                                              景。组件的kubernetes实现为kubernetes.kubernetes,适⽤于kubernetes环境。
                                              为了区分,以下通过kubernetes表示runtime的组件, k8s表示kubernetes环境
                                              go-micro中的微服务节点对应kubernetes中的pod,可通过Deployment和Service进⾏控制。故对runtime对微服
                                              务的管理,就是对k8s资源的管理。
                                              kubernetes包含以下信息
                                              kubernetes客户端
                                              kubernetes客户端⽤于请求kubernetes的kube-apiserver。管理k8s资源。
                                              监听微服务事件:runtime组件启动后,会监听从微服务传递过来的事件,事件包含:服务创建,服务更新,服务
                                              删除。
                                              传递到kubernetes:调⽤kube-apiserver,操作Deployment和Service资源。
                                              配置信息
                                              Update(*Service, ...UpdateOption) error
                                              // Remove a service
                                              Delete(*Service, ...DeleteOption) error
                                              // Logs returns the logs for a service
                                              Logs(*Service, ...LogsOption) (LogStream, error)
                                              // Start starts the runtime
                                              Start() error
                                              // Stop shuts down the runtime
                                              Stop() error
                                              // String describes runtime
                                              String() string
                                              }



                                              以kubernetes实现为例。 go-micro的默认实现为runtime.runtime,只适⽤于所有服务在同⼀个操作系统中的场景。组件的kubernetes实现为kubernetes.kubernetes,适⽤于kubernetes环境。


                                              为了区分,以下通过kubernetes表示runtime的组件, k8s表示kubernetes环境


                                                type kubernetes struct {
                                                sync.RWMutex
                                                // options configure runtime
                                                options *runtime.Options
                                                // indicates if we're running
                                                running bool
                                                // used to stop the runtime
                                                closed chan bool
                                                // client is kubernetes client
                                                client client.Client
                                                // namespaces which exist
                                                namespaces []client.Namespace
                                                }


                                                go-micro中的微服务节点对应kubernetes中的pod,可通过Deployment和Service进⾏控制。故对runtime对微服务的管理,就是对k8s资源的管理。


                                                jwt 包含以下⼏种信息:


                                                #1

                                                kubernetes客户端


                                                kubernetes客户端⽤于请求kubernetes的kube-apiserver。管理k8s资源。



                                                监听微服务事件:runtime组件启动后,会监听从微服务传递过来的事件。


                                                事件包含:服务创建,服务更新,服务删除


                                                传递到kubernetes:调⽤kube-apiserver,操作Deployment和Service资源。



                                                #2

                                                配置信息


                                                包含的配置信息有:定时任务(组件启动后执⾏,可创建微服务事件), kubernetes信息(镜像名称,资源类型等)



                                                #3

                                                状态信息


                                                微服务运⾏的命名空间
                                                组件的运⾏状态(启动,关闭)

                                                profile.Profile

                                                pprof组件,采集性能数据


                                                  type Profile interface {
                                                  // Start the profiler
                                                  Start() error
                                                  // Stop the profiler
                                                  Stop() error
                                                  // Name of the profiler
                                                  String() string
                                                  }


                                                  以profiler实现为例。 实现结构体为pprof.profiler


                                                    type profiler struct {
                                                    opts profile.Options
                                                    sync.Mutex
                                                    running bool
                                                    // where the cpu profile is written
                                                    cpuFile *os.File
                                                    // where the mem profile is written
                                                    memFile *os.File
                                                    }


                                                    profiler 包含以下⼏种信息:


                                                    #1

                                                    性能分析


                                                    profiler使⽤go⾃带的pprof进⾏性能分析。


                                                    cpuFile *os.File:cpu性能分析结果⽂件,通过pprof.StartCPUProfile⽅法记录。


                                                    memFile *os.File:内存性能分析结果⽂件,通过pprof.WriteHeapProfile⽅法记录。



                                                    #2

                                                    配置信息


                                                    包含的配置信息有: 分析名称(⽣成临时⽂件的名称)



                                                    #3

                                                    状态信息


                                                    状态信息包含:组件的运⾏状态。

                                                    store.Store

                                                    数据存储组件。与数据中⼼交互, go-micro数据存储组件⽀持key-value格式数据。


                                                      type Store interface {
                                                      // Init initialises the store. It must perform any required setup on the backing
                                                      storage implementation and check that it is ready for use, returning any errors.
                                                      Init(...Option) error
                                                      // Options allows you to view the current options.
                                                      Options() Options
                                                      // Read takes a single key name and optional ReadOptions. It returns matching
                                                      []*Record or an error.
                                                      Read(key string, opts ...ReadOption) ([]*Record, error)
                                                      // Write() writes a record to the store, and returns an error if the record was not
                                                      written.
                                                      Write(r *Record, opts ...WriteOption) error
                                                      // Delete removes the record with the corresponding key from the store.
                                                      Delete(key string, opts ...DeleteOption) error
                                                      // List returns any keys that match, or an empty list with no error if none matched.
                                                      List(opts ...ListOption) ([]string, error)
                                                      // Close the store
                                                      Close() error
                                                      // String returns the name of the implementation.
                                                      String() string
                                                      }


                                                      以redis实现为例。 redis实现的结构体为redis.rkv


                                                        type rkv struct {
                                                        ctx context.Context
                                                        options store.Options
                                                        Client redis.UniversalClient
                                                        }


                                                        rkv 包含以下⼏种信息:


                                                        #1

                                                        数据中⼼客户端


                                                        通过redis客户端与redis进⾏交互,实现数据的增删改查。



                                                        #2

                                                        配置


                                                        包含的配置信息有: 数据中⼼节点配置,数据库,数据表。

                                                        logger.Logger

                                                        ⽇志记录组件


                                                          type Logger interface {
                                                          // Init initialises options
                                                          Init(options ...Option) error
                                                          // The Logger options
                                                          Options() Options
                                                          // Fields set fields to always be logged
                                                          Fields(fields map[string]interface{}) Logger
                                                          // Log writes a log entry
                                                          Log(level Level, v ...interface{})
                                                          // Logf writes a formatted log entry
                                                          Logf(level Level, format string, v ...interface{})
                                                          // String returns the name of logger
                                                          String() string
                                                          }


                                                          go-micro默认⽇志记录实现为logger.defaultLogger


                                                            type defaultLogger struct {
                                                            sync.RWMutex
                                                            opts Options
                                                            }


                                                            defaultLogger 包含以下⼏种信息:


                                                            #1

                                                            日志记录



                                                            defaultLogger将⽇志记录的当前时间戳,⽇志等级,公共字段(通过Filed⽅法设置),具体信息。通过fmt.Printf函数输出到系统的STDOUT中



                                                            #2

                                                            配置


                                                            包含的配置信息有:⽇志记录等级,公共字段,输出,上下⽂等。






                                                            启动微服务 



                                                            Step 1 :启动微服务


                                                            使⽤micro.Service的Run⽅法启动微服务时,调⽤server.Server的Start⽅法来启动Server组件。


                                                            如果profile.Profile已经配置到了micro.Service的Options中,调⽤profile.Profile的Start⽅法来启动Profile组件。



                                                            Step 2 :开启服务关闭监听


                                                            服务启动完成后,开启服务关闭监听,服务关闭有以下两种⽅式:

                                                            • 信号关闭:系统接收到SIGTERM、 SIGINT、 SIGQUIT或SIGKILL信号时,关闭服务。可通过配置项(Signal)取消该关闭⽅式。

                                                            • 上下⽂关闭:触发了micro.Service中的定义的上下⽂的取消⽅法时,关闭服务。



                                                            Step 3 :停⽌Server组件


                                                            使⽤server.Server的Stop⽅法,停⽌Server组件。



                                                            Step 4 :停⽌Profile组件


                                                            使⽤profile.Profile的Stop⽅法,停⽌Profile组件。



                                                            下面我们具体来看其中几点。


                                                            启动Server组件




                                                            启动Server

                                                            使⽤server.Server的Start⽅法启动Server


                                                            开启服务监听

                                                            使⽤transport.Transport的Listen⽅法开启服务监听。


                                                            开启消息监听

                                                            使⽤broker.Broker的Connect⽅法开启消息监听。


                                                            开启服务注册

                                                            先使⽤RegisterCheck定义的⽅法进⾏服务注册检查。检查通过后,再使⽤Register⽅法进⾏服务注册。


                                                            处理请求线程

                                                            处理请求线程,是⽤来接收到服务请求。并进⾏后续处理。


                                                            服务注册⼼跳保持线程



                                                            • 统正常运⾏时,开启定时任务。每隔30s使⽤RegisterCheck定义的⽅法进⾏注册检查,检查通过时,直接使⽤Register注册;检查失败时,先使⽤Deregister⽅法取消注册,再使⽤Deregister⽅法重新注册。

                                                            • 使⽤通道监听服务状态,当收到服务关闭时,停⽌定时任务,使⽤Deregister⽅法取消注册。



                                                            服务注册(Register⽅法)



                                                            • 始注册后,先从缓存中获取服务信息,由于需要进⾏服务注册⼼跳保持机制,每次注册的服务信息不会发⽣变化,故可以将需要注册的服务信息进⾏缓存。

                                                            • 服务已经进⾏了缓存,直接获取缓存中的服务信息,使⽤registry.Registry的Register⽅法在注册中⼼注册务。

                                                            • 服务未进⾏缓存,先⽣成节点信息。节点信息包含有:服务名称,服务版本,服务监听的端点(服务请求处理端点和消息通知处理端点),节点信息。

                                                            • 使⽤broker.Broker的Subscribe⽅法在消息中⼼订阅消息,消息订阅端是⽤来绑定订阅的消息和对该消息的处理逻辑。

                                                            • 使⽤regisry.Registry的Register⽅法在注册中⼼注册服务。注册失败时会进⾏重试,共3次。

                                                            • 注册成功后,将服务信息进⾏缓存。



                                                            取消注册(Deregister⽅法)



                                                            • 取消注册时,先⽣成节点的简要信息。

                                                            • 根据节点简要信息,使⽤registry.Registry的Deregister⽅法取消该节点的注册。

                                                            • 调⽤每个订阅端端Unsubscribe⽅法,在消息中⼼取消订阅

                                                            • 清除服务信息的缓存

                                                            启动Profile组件

                                                            使⽤go⾃带的pprof进⾏启动性能分析。

                                                            停⽌Server组件

                                                            使⽤通道通知服务注册⼼跳保持线程服务已关闭,修改服务的启动状态。

                                                            停⽌Profile组件

                                                            停⽌pprof性能分析。





                                                            本期源码阅读之旅到此就结束了!

                                                            如有疑问

                                                            欢迎加入社群一起讨论哦⬇

                                                            本期作者 

                                                            刘健  



                                                            更多精彩内容 





                                                            了解云基地,就现在!


                                                            IT技术哪家

                                                            神州数码最在行

                                                            行业新星后起之秀

                                                            历史虽不长,但实 力 强





                                                            文章转载自神州数码云基地,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                                            评论