


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
配置
节点信息配置:包含服务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性能分析。


本期源码阅读之旅到此就结束了!
如有疑问
欢迎加入社群一起讨论哦⬇

本期作者
刘健


更多精彩内容



了解云基地,就现在!
IT技术哪家强
神州数码最在行
行业新星,后起之秀
历史虽不长,但是实 力 强















