go-zookeeper库解析

基于 zookeeper 可以进行数据配置及服务发现等功能。我们使用 go-zookeeper 作为客户端访问 zookeeper。本文主要是对 go-zookeeper 的源码解析分析。

总体执行逻辑

入口是 Connect 函数, 需要提供 servers 列表及 session 过期时间。第三个参数使用的回调方式来设置 conn 的属性。

Connect 大体逻辑如下:

  1. servers 列表随机,防止产生热点

  2. DNSHostProvider 实现 DNS 查询, 把 host 转换成 address(ip 地址)

  3. 开启 goroutine 循环

    a. 建立网络连接

  • 使用轮询的方式,选取ip地址
  • 如果建联成功, 会打印 2018/03/03 11:26:53 Connected to 127.0.0.1:2181 类似的提示

    b. 调用 authenticate, 协调生产 SessionID , 2018/03/03 11:26:53 Authenticated: id=99617148944318466timeout=4000, id 就是sessionId, timeout 是服务端返回的 session 超时时间。根据服务端返回的 timeout 数据设置 pingInterval。

    c. 开启两个 goroutine, 一个 sendLoop 循环, 一个 recvLoop 循环

    d. sendLoop 循环, 如果有 send 数据则发送数据,否则,根据 pingInterval 时间发送心跳包

    e. recvLoop 循环接收网络数据, 前4个字节是包的长度,根据长度创建 buf 大小,存储收到的数据。返回的头文件中有 Xid 字段,这个是请求传过去的,然后原样返回。所有的 request 会放到一个 map 中,Xid 就是其中的 key 。如果接受到的数据是 watcher 数据,Xid 为 固定值-1. recvLoop 会根据 path 和 watcher 类型查找全局 map 中对应的数据,把 event事件放到对应的channel中。 监听事件只生效一次,然后会关闭channel,删除全局对象。

单条命令执行逻辑

  1. 先验证路径是否合法, zookeeper 对 path 要严格的要求
  2. 组装 request 结构, 其中 Xid 是原子自增的数值, 然后发送给 sendChan。有些命令是要设置监听数据的,服务端如果有变更的话,会通知到客户端。 一个 request 要设置监听数据,可以 在 recvFunc 中调用 addWatcher 方法 。
  3. sendLoop 从 sendChan 获取 request 数据,调用 sendData 发送, sendData 封装包结构发送网络数据。 把 request 放入到 requests map 数据中,其中 key 为 Xid。
  4. sendLoop 监听网络返回的数据,进行解码。 找到对应xid, 然后从 requests 找到对应的 req, 如果req 中设置过recvFunc, 则回调 recvFunc 。

客户端关闭逻辑

客户端如果要关闭连接,需要调用 Close 方法。

  1. 关闭 shouldQuit channel
  2. 发给 sendChan 关闭请求,opcode 为关闭操作
  3. sendLoop 调用 sendData 发送关闭请求到服务端
  4. recvLoop 接收到关闭请求回复,跳出循环,关闭 closeChan
  5. sendLoop 接收到 closeChan 请求,跳出循环,关闭网络连接
  6. loop 循环中设置关闭状态, 根据 shouldQuit 刷新还未发送的request, 设置response, 跳出loop循环

总结

  1. 客户端包含三个循环, loop, sendLoop, recvLoop。循环的整体逻辑如下图所示

    http://blog.bruceding.com/wp-content/uploads/2018/03/go-zookeeper.png

  2. 如果遇到网络错误,或者 连接的 zk server 断开的情况下,recvLoop 会退出循环,进而导致 sendLoop 退出循环,然后 loop 的阻塞状态会退出,导致重新循环进行网络连接。只要调用 Connect 方法成功,后续的连接状态客户端会保证的,上层的应用方不必关心,也无需重新调用 Connect, 如果多次调用 Connect, 会生成多个网络连接。

  3. 全局的数据,比如 requests map, 会被不同的 goroutine 使用,使用要注意加锁。

  4. 基于 channel 进行通信

  5. 如果要关闭 go-zookeeper, 务必要调用 Close 方法

此条目发表在GO分类目录,贴了标签。将固定链接加入收藏夹。

go-zookeeper库解析》有 1 条评论

  1. I am usually in order to running a blog as well as i really admire your site content. This content features really peaks my interest. I’m going to bookmark your current web site and also maintain examining for brand spanking new data.

发表评论

电子邮件地址不会被公开。