作者: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 = -112StateConnected  = 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()进行选举。