Go Micro 底层是如何将服务注册到 Consul 的


consul-arch-single.png

前面两篇分享学院君已经简单介绍了基于 Go Micro 框架实现服务接口的发布和调用,接下来,我们以 Consul 作为注册中心为例,介绍 Go Micro 框架底层是如何将服务注册到 Consul 的。

服务注册与发现流程

服务的注册和发现是微服务架构中必不可少的重要一环,Go Micro 为此提供了专门的接口 Registry 来处理,实现该接口的组件即可作为微服务的注册中心用于服务注册与发现,在我们的示例中以 Consul 作为注册中心,所有微服务服务端启动时,会将服务信息注册到 Consul,然后客户端调用服务时,会从 Consul 中查询服务接口信息,再发起请求,对应流程图如下:

Consul

以前面介绍的 GreeterService 为例:

  1. GreeterService 服务端启动时,会向 Consul 发送一个 POST 请求,告诉 Consul 自己的 IP 和端口;
  2. Consul 接收到 GreeterService 的注册请求后,每隔 10s(默认)会向 GreeterService 发送一个健康检查的请求,检验 GreterService 是否有效(心跳检测);
  3. 当客户端以 HTTP 接口方式发送 GET 请求 /greeter/say/helloGreeterService 时,会先从 Consul 中拿到一个存储对应服务 IP 和端口的临时表,并从表中查询 GreeterService 的 IP 和端口,再发送 GET 方式请求到 /greeter/say/hello。该临时表每隔 10s 会更新,只包含有通过了健康检查的 Service。此外,为了提高性能和系统可用性,往往会缓存服务信息到本地,如果服务部署在多个机器,还会使用负载均衡算法选择指定服务端通信。

服务注册底层实现细节

我们先来看看服务端启动时是如何将服务信息注册到 Consul 的,打开 ~/go/hello/src/hello/main.go 这个服务端主入口文件,可以在 main 函数末尾看到这段代码:

service.Run() 是服务启动的入口函数,对应的源码位于 go-micro/service.go

这里面会调用 service.Start() 方法:

该方法会依次执行服务启动前逻辑、启动逻辑和启动后逻辑,我们重点关注服务启动过程中做了啥,追踪 s.opts.Server.Start() 方法,这段源码位于 go-micro/server/rpc_server.go 文件中的 (s *rpcServer) Start() 函数,该函数中的代码就是咱们服务启动的核心逻辑所在了,由于涉及到的代码量比较大,我们重点关注服务注册部分:

这里先对上下文环境做检测,没有问题才正式开始服务注册,对应的注册逻辑位于当前文件下的 (s *rpcServer) Register() 方法,在该方法中,会获取服务所在机器的 IP、端口以及服务名称、节点ID、元数据、处理器列表、订阅者等信息并将其注册到系统默认的注册中心:

这里我们通过系统环境变量 MICRO_REGISTRY=consul 指定默认注册中心为 Consul,所以我们直接去 go-micro/registry/consul/consul.go 中看 (c *consulRegistry) Register 方法的实现,这个方法代码量也比较大,前面一大堆逻辑都是做环境检测和变量的初始化,我们直接拉到后面的服务注册部分:

具体注册逻辑在 c.Client.Agent().ServiceRegister 对应的方法中

系统会发起一个 PUT 请求到 Consul 的服务注册接口 /v1/agent/service/register,并将服务注册信息作为请求实体传递过去,请求失败则返回错误信息,请求成功,则可以在 Consul 上看到注册的新服务。

以上,就是 Go Micro 框架服务注册的底层实现细节,基于其它组件的注册中心总体流程也是如此,只是不同注册中心实现服务注册的细节有所差异罢了,下一篇,学院君将给大家介绍客户端发现服务、调用服务的底层实现细节。


<< 上一篇: 通过 HTTP 请求调用 Go Micro 提供的微服务接口

>> 下一篇: 基于 Consul 的 Go Micro 客户端服务发现是如何实现的