写点什么

超细!细说 Zookeeper 选举的一个案例(下)

  • 2021 年 12 月 20 日
  • 本文字数:2317 字

    阅读完需:约 8 分钟

作者:ReganYue

来源:恒生LIGHT云社区

超细!细说 Zookeeper 选举的一个案例

今天我们来带着大家实现用 Zookeeper 实现选举的案例,帮助大家更好的学习 Zookeeper。

六、判断是否连接 Zookeeper

func (electionManager *ElectionManager) isConnected() bool {    if electionManager.ZKClientConn == nil {        return false    } else if electionManager.ZKClientConn.State() != zk.StateConnected {        return false    }    return true}
复制代码


在初始化 Zookeeper 连接时需要判断是否连接了 Zookeeper,其实我们可以看连接是否为 nil 值来判断有没有连接,如果想判断连接是否有问题的话,我们最好用连接的 State()方法,如果是 zk.StateConnected,就表示连接成功了,如果是其他就表示连接异常,下面列举连接异常和成功的值。


StateUnknown           State = -1StateDisconnected      State = 0StateConnecting        State = 1StateAuthFailed        State = 4StateConnectedReadOnly State = 5StateSaslAuthenticated State = 6StateExpired           State = -112
StateConnected = State(100)StateHasSession = State(101)
复制代码


可以看到,zk.StateConnected 也就是 100,所以这里可能可以将 zk.StateConnected 替换为 100,我也不知道是否可行,你可以试一试~ StateUnknown 也就是-1 表示状态是未知的,StateDisconnected 也就是 0 表示状态是未连接,其它我就不细说了。

七、选举的逻辑

func (electionManager *ElectionManager) Run() {    err := electionManager.electMaster()    if err != nil {        fmt.Println(err)    }    electionManager.watchMaster()}
复制代码


是不是很眼熟,这就是 main 函数中开辟协程运行的东西——选举。


很简单,直接进行选举选出 master,然后对 master 节点进行监听。

八、选举逻辑

func (electionManager *ElectionManager) electMaster() error {    err := electionManager.initConnection()    if err != nil {        return err    }    isExist, _, err := electionManager.ZKClientConn.Exists(electionManager.ZKConfig.RootPath)    if err != nil {        return err    }    if !isExist {        path, err := electionManager.ZKClientConn.Create(electionManager.ZKConfig.RootPath,            nil, 0, zk.WorldACL(zk.PermAll))        if err != nil {            return err        }        if electionManager.ZKConfig.RootPath != path {            return errors.New("创建的" + electionManager.ZKConfig.RootPath + " !=" + path)        }    }
masterPath := electionManager.ZKConfig.RootPath + electionManager.ZKConfig.MasterPath path, err := electionManager.ZKClientConn.Create(masterPath, nil, zk.FlagEphemeral, zk.WorldACL(zk.PermAll)) if err == nil { if path == masterPath { fmt.Println("选举master成功") electionManager.IsMaster <- true } else { return errors.New("创建的" + masterPath + "!=" + path) } } else { //创建master节点失败 fmt.Println("选举master失败!", err) electionManager.IsMaster <- false } return nil}
复制代码


要开始选举,必须要先连接 Zookeeper,我们编写的 initConnection()进行连接 zk 并可以通过返回值来判断连接是否有问题。


然后判断 zk 中是否存在根目录,如果没有,就创建根目录,根目录一般数据先不设置,flags 是为 0,要创建持久化节点,权限不进行控制。


来介绍一下这个 Create()叭~


Create()有四个参数,第一个是要创建的路径,第二个参数是节点中的数据内容,第三个参数是节点类型参数,flag=0 表示这是一个持久化的节点,第四个参数是权限。有下面这些权限。


PermRead = 1 << iotaPermWritePermCreatePermDeletePermAdminPermAll = 0x1f
复制代码


使用 zk.WorldACL(zk.PermAll)表示该节点没有权限限制


然后再拼接 master 地址,创建 master 节点,因为需要创建个临时节点,所以 Create()中的第三个参数参数使用 zk.FlagEphemeral 表示创建临时节点。创建成功,表示选举 master 成功,哪个客户端节点创建了 master,认为是选举哪个节点作为 master 节点。


创建成功后要给连接的 isMaster 写入 true,不成功则写入 false。

九、监听 Master 节点

func (electionManager *ElectionManager) watchMaster() error {    for {            children, state, childCh, err := electionManager.ZKClientConn.ChildrenW(electionManager.ZKConfig.RootPath + electionManager.ZKConfig.MasterPath)        if err != nil {            fmt.Println("监听失败!", err)        }        fmt.Println("监听到子节点", children, state)        select {        case childEvent := <-childCh:            if childEvent.Type == zk.EventNodeDeleted {                fmt.Println("接收到znode的删除事件", childEvent)                fmt.Println("开始选举新的master...")                err = electionManager.electMaster()                if err != nil {                    fmt.Println("选举新的master失败", err)                }            }        }
}}
复制代码


需要监听 zookeeper 根节点下的子节点,因为如果连接断开或对应的子 znode 被删除,则触发重新选举,所以需要监听目录下所有子节点。


ChildrenW()会返回监听事件,如果监听到子节点被删除,也就是监听到的事件类型是 zk.EventNodeDeleted,就重新调用 electMaster()进行选举。

发布于: 2 小时前阅读数: 5
用户头像

还未添加个人签名 2018.11.07 加入

还未添加个人简介

评论

发布
暂无评论
超细!细说Zookeeper选举的一个案例(下)