基本使用
注册
client, err := zk.NewClient([]string{"localhost:2181"},logger)
if err != nil{
panic(err)
}
register := zk.NewRegistrar(client,zk.Service{
Path: "/services/hello",
Name: "abc",
Data: []byte("http://127.0.0.1:8080"),
},logger)
register.Register()
发现
client, err := zk.NewClient([]string{"localhost:2181"},logger)
if err != nil{
panic(err)
}
instancer , err := zk.NewInstancer(client,"/services/hello/abc",logger)
if err != nil {
panic(err)
}
duration := 500 * time.Millisecond
ctx := context.Background()
factory := helloFactory(ctx, "GET", "hello")
endpointer := sd.NewEndpointer(instancer, factory, logger)
endpointers,_ := endpointer.Endpoints()
底层原理
目录结构
.
├── client.go 客户端
├── client_test.go
├── doc.go
├── instancer.go 服务实例
├── instancer_test.go
├── integration_test.go
├── logwrapper.go
├── registrar.go 注册器
└── util_test.go
目录中主要的是这三个文件,client.go instancer.go registrar.go
client.go
type Client interface {
//获取一组value通过key前缀
GetEntries(path string) ([]string, <-chan zk.Event, error)
//watch指定前缀的key
CreateParentNodes(path string) error
//注册服务
Register(s *Service) error
//注销服务
Deregister(s *Service) error
//停止zk链接
Stop()
}
type client struct {
*zk.Conn //组合 github.com/samuel/go-zookeeper/zk struct Conn
clientConfig
active bool
quit chan struct{}
}
func NewClient(servers []string, logger log.Logger, options ...Option) (Client, error)
func (c *client) CreateParentNodes(path string)
主要包含以下5个函数
-
NewClient 创建zk客户端,client.Conn
-
GetEntries client.Get 获取value
-
Deregister client.Delete 删除zk中指定的key
-
CreateParentNodes 保证key中的父节点都已经被创建。由于zk创建子节点时父节点必须都存在,如:/a/b/c,当/a/b节点不存在时,/a/b/c节点无法创建
-
Register
- CreateParentNodes函数创建所有父节点,已存在则跳过
- client.CreateProtectedEphemeralSequential函数,创建一个保护 临时 顺序 节点(ProtectedEphemeralSequential),同时将value存在此节点中。
- 保护顺序临时节点
- 示例:cc83db041ac654566228b72cbd541bcb5-abc0000000006,其中加粗字体为GUID,_c_为默认前缀,abc0000000006为后缀
- 临时节点,当zk链接会话关闭后,该节点就会被删除。
- 顺序节点,创建的节点的名称以GUID作为前缀。如果节点创建失败,则会发生正常的重试机制。在重试过程中,首先搜索父路径,寻找包含GUID的节点。如果找到该节点,则假定它是第一次尝试成功创建并返回给调用者的丢失节点。
- 保护节点,key自增后缀确保节点名称的唯一性
registrar.go
type Registrar struct {
//zk客户端
client Client
//注册的服务
service Service
logger log.Logger
}
//服务的key和地址
type Service struct {
Path string // 服务发现命名空间: /service/hello/
Name string // 服务名称, example: abc
Data []byte // 服务实例数据存在, 如: 10.0.2.10:80
node string // 存储 ProtectedEphemeralSequential(保护临时顺序)节点的名称,便于Deregister函数注销服务
}
func NewRegistrar(client Client, service Service, logger log.Logger) *Registrar
func (r *Registrar) Register()
func (r *Registrar) Deregister()
包含以下3个函数
- NewRegistrar 创建 Registrar
- Register 调用 client.go中 Register 方法
- Deregister 调用 client.go中 Deregister 方法
instancer.go
type Instancer struct {
//实例缓存
cache *instance.Cache
//zk客户端
client Client
//服务zk节点值
path string
logger log.Logger
//Instancer 主动退出 通道
quitc chan struct{}
}
func NewInstancer(c Client, path string, logger log.Logger) (*Instancer, error)
func (s *Instancer) loop(eventc <-chan zk.Event)
func (s *Instancer) Stop()
func (s *Instancer) Register(ch chan<- sd.Event)
func (s *Instancer) state() sd.Event {
主要包含以下5个函数
- NewInstancer
- 调用 client.go GetEntries函数,获取对应的一组服务地址
- loop
- 监听服务对应的key
- Stop
- 关闭服务监听
- Register
- Deregister