Author: Regan Yue
Source: Hang Seng LIGHT cloud community
Ultra fine! A case of Zookeeper election
Today, let's take you to the case of realizing election with Zookeeper to help you better learn Zookeeper.
6, Determine whether to connect Zookeeper
func (electionManager *ElectionManager) isConnected() bool { if electionManager.ZKClientConn == nil { return false } else if electionManager.ZKClientConn.State() != zk.StateConnected { return false } return true }
When initializing the Zookeeper connection, we need to judge whether Zookeeper is connected. In fact, we can judge whether there is a connection by whether the connection is nil. If we want to judge whether there is a problem with the connection, we'd better use the connected State() method. If it is ZK Stateconnected indicates that the connection is successful. If it is other, it indicates that the connection is abnormal. The values of connection exception and success are listed below.
StateUnknown State = -1 StateDisconnected State = 0 StateConnecting State = 1 StateAuthFailed State = 4 StateConnectedReadOnly State = 5 StateSaslAuthenticated State = 6 StateExpired State = -112 StateConnected = State(100) StateHasSession = State(101)
As you can see, ZK Stateconnected is 100, so ZK Stateconnected is replaced by 100. I don't know whether it is feasible. You can try ~ StateUnknown, that is, - 1 means the state is unknown, StateDisconnected, that is, 0 means the state is not connected. I won't elaborate on others.
7, Logic of election
func (electionManager *ElectionManager) Run() { err := electionManager.electMaster() if err != nil { fmt.Println(err) } electionManager.watchMaster() }
Isn't it familiar? This is what opens up the co process operation in the main function - election.
It is very simple. Directly select the master and then listen to the master node.
8, Election logic
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("Created" + 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("election master success") electionManager.IsMaster <- true } else { return errors.New("Created" + masterPath + "!=" + path) } } else { //Failed to create master node fmt.Println("election master Failed!", err) electionManager.IsMaster <- false } return nil }
To start the election, you must first connect to Zookeeper. We write initConnection() to connect zk and judge whether there is a problem with the connection through the return value.
Then judge whether there is a root directory in zk. If not, create a root directory. Generally, the root directory data is not set first, and the flags are 0. To create a persistent node, the permissions are not controlled.
Let's introduce the Create() function~
Create() has four parameters. The first parameter is the path to be created, the second parameter is the data content in the node, the third parameter is the node type parameter, flag=0 indicates that this is a persistent node, and the fourth parameter is permission. Have the following permissions.
PermRead = 1 << iota PermWrite PermCreate PermDelete PermAdmin PermAll = 0x1f
Use ZK Worldacl (zk. Permall) indicates that the node has no permission restrictions
Then splice the master address to create a master node. Because a temporary node needs to be created, the third parameter in Create() uses ZK Flagephemeral means to create a temporary node. Successful creation indicates that the election of the master is successful. Which client node has created the master is considered to be the election of which node as the master node.
After successful creation, write true to the connected isMaster. If unsuccessful, write false.
9, Listen to Master node
func (electionManager *ElectionManager) watchMaster() error { for { children, state, childCh, err := electionManager.ZKClientConn.ChildrenW(electionManager.ZKConfig.RootPath + electionManager.ZKConfig.MasterPath) if err != nil { fmt.Println("Monitoring failed!", err) } fmt.Println("Listen to child nodes", children, state) select { case childEvent := <-childCh: if childEvent.Type == zk.EventNodeDeleted { fmt.Println("Received znode Delete event for", childEvent) fmt.Println("Start Electing new master...") err = electionManager.electMaster() if err != nil { fmt.Println("Elect a new master fail", err) } } } } }
You need to listen to the child nodes under the root node of zookeeper. If the connection is disconnected or the corresponding child znode is deleted, re-election will be triggered. Therefore, you need to listen to all child nodes under the directory.
ChildrenW() will return the listening event. If the child node is deleted, that is, the event type is ZK After eventnodedeleted, the electMaster() is called again for election.