写点什么

[ Kitex 源码解读 ] 服务注册

作者:baiyutang
  • 2022 年 7 月 22 日
  • 本文字数:2007 字

    阅读完需:约 7 分钟

[ Kitex 源码解读 ] 服务注册

Kitex

如果你还不了解 Kitex,可以看看《[ CloudWeGo 微服务实践 - 01 ] 开篇》。

如果你想参与 CloudWeGo 社区,给 Kitex 和其他组件贡献代码,可以看《如何给 CloudWeGo 做贡献》。

服务注册

服务注册与服务发现是 RPC 框架中最重要的组件,地位仅次于加解密与通信的实现。在 Kitex 中,注册中心已经支持了主流的各个组件,如 registry-etcdregistry-nacosregistry-zookeeperregistry-polarisregistry-eurekaregistry-consul 等。


服务注册是在服务端做的,将已启动的服务实例添加到注册中心。

用法

我们以 nacos 为例,代码如下:

https://github.com/kitex-contrib/registry-nacos/blob/main/example/basic/server/main.go

func main() {    	// 通过默认配置获取一个注册中心的实例    	// 方法内部有通过默认配置创建一个 nacos 客户端,方便后续与 nacos 交互	r, err := registry.NewDefaultNacosRegistry()	if err != nil {		panic(err)	}  	svr := hello.NewServer(		new(HelloImpl),          		// 以 WithOption 的方式指定注册中心		server.WithRegistry(r),    		server.WithRegistryInfo(&kitexregistry.Info{ServiceName: "Hello"}),		server.WithServiceAddr(&net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 8080}),	)	if err := svr.Run(); err != nil {		log.Println("server stopped with error:", err)	} else {		log.Println("server stopped")	}}
复制代码


探索过程

实验条件

我们以 registry-nacos 的 custom-config 代码示例为基础进行改造。

  • registry-nacos v0.0.1

  • MacOS 12.4

  • Goland

  • Docker v20.10.12

环境准备

  1. git clone git@github.com:kitex-contrib/registry-nacos.git 注意要与 Kitex 同级目录下,方便后续如果有必要进行调试。

  2. 在 registry-nacos 根目录下执行 make prepare 启动 nacos 注册中心,若命令不支持可手动执行 docker 相关命令,务必确保启动注册中心。

运行案例

我们运行的案例是 custom-config 的 demo。这里的 nacos 客户端参数都可配置,方便调试。

启动服务端

 go run example/custom-config/server/main.go
复制代码



Nacos 管理后台查看

后台地址:http://localhost:8848/nacos/index.html

账号密码都是 nacos

服务管理 > 服务列表,能看到一组服务


详情中也能看到具体的实例


以上可以证明是注册成功的。

终止服务

ctrl + c 停止服务端


Nacos 管理后台查看

刷新刚刚的服务详情页面,实例也没有了


源码分析

接口

main.go 文件中,我们看到 NewServer 时,server.WithRegistry 接收我们制定的服务注册组件


// kitex/server/option.go:217
// WithRegistry to set a Registry to register servicefunc WithRegistry(r registry.Registry) Option { return Option{F: func(o *internal_server.Options, di *utils.Slice) { di.Push(fmt.Sprintf("WithRegistry(%T)", r))
o.Registry = r }}}
复制代码

由此我们能看到接收的参数也是一个接口类型,后续我们定制扩展服务注册组件也是基于此的。

// kitex/pkg/registry/registry.go:28
// Registry is extension interface of service registry.type Registry interface { Register(info *Info) error Deregister(info *Info) error}
复制代码

Register

从上一步的 WithRegistry 出发,我们看到该函数有一个赋值操作,最终的服务注册组件来到了 Options.Registry 结构体及字段中:


我们使用 Goland 的追踪功能,大概能看到一些线索

最下边好像是执行了 Register 函数:


由此能看到 waitExit 函数中,是有一个延迟注册的逻辑在的。我们再网上追踪,看到引用的地方:

由此也就明了,在服务启动时,尝试启动服务后,会调用注册函数。因为整个链路都是接口,所以就能把关键逻辑抽离到具体的组件中单独维护,也完美的体现了之前我们总结的《整体设计理念》:保证核心链路不变;只对可变部分扩展等。


综上,Kitex 框架保证了在核心链路中对服务信息的注册动作,具体的注册逻辑要去到各自 registry-xxx 的包中实现,我们以 registry-nacos 为例看个大概:

registry-nacos/registry/registry.go:76

Deregister

WithRegistry 出发,我们看到该函数有一个赋值操作,最终的服务注册组件来到了 Options.Registry 结构体及字段中:


我们使用 Goland 的追踪功能,大概能看到一些线索:

进到 server.go:237 处:

由此能看到是在服务终止时调用了 Deregister 函数,这里执行了注销服务的动作。再往上走,我们依旧能看到 Stop 函数是在 Run 中执行,并且是在 waitExit 函数之后,waitExit 是在等待退出信号,说明走到 Stop 时已经知道要退出了。



综上,Kitex 框架保证了在核心链路中对服务信息的注销动作,具体的注销逻辑要去到各自 registry-xxx 的包中实现,我们以 registry-nacos 为例看个大概:

registry-nacos/registry/registry.go:76


定制扩展

官网有服务注册扩展,如果想了解具体的实践,可以参考之前写过的《[ CloudWeGo 微服务实践 - 08 ] Nacos 服务发现扩展 (2)

发布于: 2022 年 07 月 22 日阅读数: 49
用户头像

baiyutang

关注

广州 2017.12.13 加入

Microservices | Golang | Cloud Nitive | “Smart work,Not hard”

评论

发布
暂无评论
[ Kitex 源码解读 ] 服务注册_Go_baiyutang_InfoQ写作社区