Redis实现服务注册与服务发现源码阅读
背景
近期在看开源项目CloudWeGo中看到目前GoLang微服务框架Hertz中支持通过Redis实现服务注册与服务发现功能。便想着阅读下源码
源码阅读
gut clone了hertz-contrib后看到在一级目录下有目前各种主流的服务注册与发现的实现方案。为了便于学习选择阅读redis
服务注册源码分析
看到redis/example/server/main.go中有服务注册的实现示例
func main() {
r := redis.NewRedisRegistry("127.0.0.1:6379")
addr := "127.0.0.1:8888"
h := server.Default(
server.WithHostPorts(addr),
server.WithRegistry(r, ®istry.Info{
ServiceName: "hertz.test.demo",
Addr: utils.NewNetAddr("tcp", addr),
Weight: 10,
Tags: nil,
}),
)
h.GET("/ping", func(_ context.Context, ctx *app.RequestContext) {
ctx.JSON(consts.StatusOK, utils.H{
"ping": "pong"})
})
h.Spin()
}
代码主要逻辑是实现一个简单的webservice,其中用到了服务注册机制。可以看到,在hertz中服务注册可以通过配置engine的形式在webservice初始化时定义,其中
r := redis.NewRedisRegistry("127.0.0.1:6379")
定义了一个服务注册的地址,即要把这个微服务注册到哪个主机中。而server.WithRegistry()使得服务初始化时引入了这个服务注册。Info即是服务注册的相关信息
进入redis/registry.go查看服务注册的定义,可以看到redis服务注册是实现的registry.Registry接口
var _ registry.Registry = (*redisRegistry)(nil)
type redisRegistry struct {
client *redis.Client
rctx *registryContext
mu sync.Mutex
wg sync.WaitGroup
}
type registryContext struct {
ctx context.Context
cancel context.CancelFunc
}
// Registry is extension interface of service registry.
type Registry interface {
Register(info *Info) error
Deregister(info *Info) error
}
// Info is used for registry.
// The fields are just suggested, which is used depends on design.
type Info struct {
// ServiceName will be set in hertz by default
ServiceName string
// Addr will be set in hertz by default
Addr net.Addr
// Weight will be set in hertz by default
Weight int
// extend other infos with Tags.
Tags map[string]string
}
registry.Registry通过Register(info *Info)和Deregister(info *Info)描述服务注册与服务发现
接下来看如何创建一个redis服务注册
// NewRedisRegistry creates a redis registry
func NewRedisRegistry(addr string, opts ...Option) registry.Registry {
redisOpts := &redis.Options{
Addr: addr,
Password: "",
DB: 0,
}
for _, opt := range opts {
opt(redisOpts)
}
rdb := redis.Ne