扫码阅读
手机扫码阅读

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

507 2023-09-21


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, BidiStreamhelloworld.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 nameName() string// Init initialises optionsInit(...Option)// Options returns the current optionsOptions() Options// Client is used to call servicesClient() client.Client// Server is for handling requests and eventsServer() server.Server// Run the serviceRun() error// The service implementationString() string}

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

type service struct {opts Optionsonce sync.Once}

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


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

核心组件

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

server.Server

微服务的服务端

type Server interface {// Initialise optionsInit(...Option) error// Retrieve the optionsOptions() Options// Register a handlerHandle(Handler) error// Create a new handlerNewHandler(interface{}, ...HandlerOption) Handler// Create a new subscriberNewSubscriber(string, interface{}, ...SubscriberOption) Subscriber// Register a subscriberSubscribe(Subscriber) error// Start the serverStart() error// Stop the serverStop() error// Server implementationString() string}

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

type rpcServer struct {router *routerexit chan chan errorsync.RWMutexopts Optionshandlers map[string]Handlersubscribers map[Subscriber][]broker.Subscriber// marks the serve as startedstarted bool// used for first registrationregistered bool// subscribe to service namesubscriber broker.Subscriber// graceful exitwg *sync.WaitGrouprsvc *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) errorOptions() OptionsNewMessage(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 uint64once atomic.Valueopts Optionspool pool.Pool}

rpcClient 包含以下⼏种信息:

#1

请求链

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


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


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

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

发送请求:

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

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

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

#2

配置

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

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

核心组件衍生

broker.Broker

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

type Broker interface {Init(...Option) errorOptions() OptionsAddress() stringConnect() errorDisconnect() errorPublish(topic string, m *Message, opts ...PublishOption) errorSubscribe(topic string, h Handler, opts ...SubscribeOption) (Subscriber, error)String() string}

/ 组件基本逻辑

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

type httpBroker struct {id stringaddress stringopts Optionsmux *http.ServeMuxc *http.Clientr registry.Registrysync.RWMutexsubscribers map[string][]*httpSubscriberrunning boolexit chan chan error// offline message inboxmtx sync.RWMutexinbox 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) errorOptions() OptionsRegister(*Service, ...RegisterOption) errorDeregister(*Service, ...DeregisterOption) errorGetService(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.Clientoptions registry.Optionssync.RWMutexregister map[string]uint64leases 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 authInit(opts ...Option)// Options set for authOptions() Options// Generate a new accountGenerate(id string, opts ...GenerateOption) (*Account, error)// Inspect a tokenInspect(token string) (*Account, error)// Token generated using refresh token or credentialsToken(opts ...TokenOption) (*Token, error)// String returns the name of the implementationString() string}

/ 组件基本逻辑

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

type jwt struct {sync.Mutexoptions auth.Optionsjwt 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.Optionsclient redis.UniversalClient}

redisCache 包含以下⼏种信息:

#1

redis客户端

⽤于和redis进⾏交互。

#2

配置

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

cmd.Cmd

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

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

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

type cmd struct {opts Optionsapp *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 interfacereader.Values// Init the configInit(opts ...Option) error// Options in the configOptions() Options// Stop the config loader/watcherClose() error// Load config sourcesLoad(source ...source.Source) error// Force a source changeset syncSync() error// Watch a value for changesWatch(path ...string) (Watcher, error)}

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

type config struct {exit chan boolopts Optionssync.RWMutex// the current snapshotsnap *loader.Snapshot// the current valuesvals reader.Values}

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

config 包含以下⼏种信息:

#1

获取数据

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

#2

监听数据

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

#3

成快照

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

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

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

#4

读取数据

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


获取:通过path获取对于值


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

runtime.Runtime

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

type Runtime interface {// Init initializes runtimeInit(...Option) error// Create registers a serviceCreate(*Service, ...CreateOption) error// Read returns the serviceRead(...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 serviceDelete(*Service, ...DeleteOption) error// Logs returns the logs for a serviceLogs(*Service, ...LogsOption) (LogStream, error)// Start starts the runtimeStart() error// Stop shuts down the runtimeStop() error// String describes runtimeString() string}

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

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

type kubernetes struct {sync.RWMutex// options configure runtimeoptions *runtime.Options// indicates if we're runningrunning bool// used to stop the runtimeclosed chan bool// client is kubernetes clientclient client.Client// namespaces which existnamespaces []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 profilerStart() error// Stop the profilerStop() error// Name of the profilerString() string}

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

type profiler struct {opts profile.Optionssync.Mutexrunning bool// where the cpu profile is writtencpuFile *os.File// where the mem profile is writtenmemFile *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 backingstorage 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 notwritten.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 storeClose() error// String returns the name of the implementation.String() string}

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

type rkv struct {ctx context.Contextoptions store.OptionsClient redis.UniversalClient}

rkv 包含以下⼏种信息:

#1

数据中⼼客户端

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

#2

配置

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

logger.Logger

⽇志记录组件

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

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

type defaultLogger struct {sync.RWMutexopts 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性能分析。

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

如有疑问

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


本期作者

原文链接: http://mp.weixin.qq.com/s?__biz=Mzg5MzUyOTgwMQ==&mid=2247515787&idx=1&sn=0fd2b0aab5f49420620b00545db3a10e&chksm=c02f852df7580c3b9f921e9f2927e535a658da768aba1309be535fd4fd921c58fa7abf7ec81b#rd