Documentation ¶
Overview ¶
Package leaderelection implements a leader election protocol in Go using the Zookeeper leader election recipe. The main steps to implement a leader election as as follows:
Initialize an election ¶
Before leader election can take place the election needs to be initialized. This involves providing a live connection to Zookeeper and an existing Zookeeper node (resource) that represents the top level of the election to the NewElection function.
election, err := NewElection(zkConn, "/election")
In the above example if zkConn is not valid or "/election" doesn't already exist an error will be returned.
Run an election ¶
Running an election will register this election instance as interested in becoming leader for the election resource that was provided in the call to NewElection (e.g., "/election"). Multiple candidates may be registered for the same election resource and contend for leadership of the resource. One will be chosen as the leader and the rest will become followers. In the event that the leader exits prior to the election terminating one of the followers will become leader. Example:
go leaderElector.ElectLeader()
This registers the candidate that created the election instance as a potential leader for the election resource. As it is started as a goroutine the candidate is expected to monitor one of several election related channels for election events.
Events that can happen while an election is running ¶
There are several channels that must be monitored during an election. The first is the channel returned by election.Status(). This channel is used to indicate to a follower that it has become leader. It is also used to signal the end of the election. This signaling occurs when the Election instance closes the Status() channel. When election end has been signaled via the closing of the Status() channel the client is expected to stop using the election. Errors may also be returned via the Status() channel. Errors generally indicate there has been a problem with the election. A network partition from Zookeeper is an example of an error that may occur. Errors are unrecoverable and mean the election is over for that candidate. The connFailCh highlights that the client owns the Zookeeper connection and is responsible for handling any errors associated with the Zookeeper connection.
for { select { case status, ok = <- leaderElector.Status(): if !ok { fmt.Println("\t\t\tChannel closed, election is terminated!!!") leaderElector.Resign() return } if status.Err != nil { fmt.Println("Received election status error <<", status.Err, ">> for candidate <", leaderElector.candidateID, ">.") leaderElector.Resign() return } fmt.Println("Candidate received status message: <", status, ">.") if status.Role == Leader { doLeaderStuff(leaderElector, status, respCh, connFailCh, waitFor) leaderElection.EndElection() // Terminates the election and signals all followers the election is over. return } case <-connFailCh: fmt.Println("\t\t\tZK connection failed for candidate <", status.CandidateID, ">, exiting") respCh <- ElectionResponse{false, status.CandidateID} leaderElector.Resign() wg.Done() return case ... // Any other channels the client may need to monitor. ... } }
The for-ever loop indicates that the election continues until one of the halting conditions described above occurs. The "case <- connFailCh:" branch is used to monitor for Zookeeper connection problems. It is up to the client to decide what to do in this event.
On channel close or Error events the client is expected to resign from the election as shown in the above code snippet. When the leader is done with the work associated with the election it is expected to terminate the election by calling the EndElection method. This is required to properly clean up election resources including termination of any existing followers.
Index ¶
Constants ¶
const ( // Follower indicates that this candidate is following another candidate/leader. Follower = iota // Leader indicates that this candidate is the leader for the election. Leader )
const ( // ElectionCompletedNotify indicates the election is over and no new candidates can be nominated. ElectionCompletedNotify = "Election is over, no new candidates allowed" // ElectionSelfDltNotify indicates that the referenced candidate was deleted. This can happen if the election is // ended (EndElection) or deleted (DeleteElection) ElectionSelfDltNotify = "Candidate has been deleted" )
Variables ¶
This section is empty.
Functions ¶
func DeleteCandidates ¶
DeleteCandidates will remove all the candidates for the provided electionName.
Types ¶
type Election ¶
type Election struct { ElectionResource string // This is the Zookeeper node that represents the overall election. Candidates // contains filtered or unexported fields }
Election is a structure that represents a new instance of a Election. This instance can then be used to request leadership for a specific resource.
func NewElection ¶
NewElection initializes a new instance of an Election that can later be used to request leadership for a specific resource.
It accepts: zkConn - a connection to a running Zookeeper instance; electionResource - resource represents the thing for which the election is being held. For example, /election/president for an election for president, /election/senator for an election for senator, etc.
It will return either a non-nil Election instance and a nil error, or a nil Election and a non-nil error.
func (*Election) ElectLeader ¶
func (le *Election) ElectLeader()
ElectLeader will make the caller a candidate for leadership and determine if the candidate becomes the leader.
ElectLeader returns: true if the candidate was elected leader, false otherwise. Candidates that aren't elected leader will be placed in the pool of possible leaders (aka followers). Candidates must explicitly resign if they don't want to be considered for future leadership.
func (*Election) EndElection ¶
func (le *Election) EndElection()
EndElection is called by the Client (leader) to signal that any work it was doing as a result of the election has completed.
Ending an election results in all followers being notified that the election is over. Followers are expected to resign from the election and move on to whatever they do when not actively involved in an Election. Ending an election also results in the freeing of all resources associated with an election.
func (*Election) Resign ¶
func (le *Election) Resign()
Resign results in the resignation of the associated candidate from the election.
Resign is called by the Client, either in a leader or follower role, to indicate that it is no longer interested in being a party to the election.
If the candidate is the leader, then a new leader election will be triggered assuming there are other candidates. If the candidate is not the leader then Resign merely results in the removal of the associated candidate from the set of possible leaders.
Resign returns nil if everything worked as expected. It will return an error if there was any problem that prevented the complete resignation of the candidate. In the event that an error is returned the client will need to perform any processing appropriate to the failure.
type Status ¶
type Status struct { CandidateID string // CandidateID is the identifier assigned to the associated Candidate for this Election. Err error // Err is used to communicate the specific error associated with this Election. // nil means there is no Err. NowFollowing string // NowFollowing is the CandidateID of the candidate that this Candidate is following. // If the followed Candidate is the Leader, then this Candidate will become Leader // if the current Leader fails. It will be an empty string ("") if the associated // candidate is the Leader. Role Role // Role is used to indicate if the associated Candidate is the Leader or a Follower. WasFollowing string // WasFollowing is the CandidateID of the Candidate that this Candidate was following }
Status is used to communicate the current state of the Election.
Directories ¶
Path | Synopsis |
---|---|
leader_crash_test
The goal of this mock worker is to simulate the behavior of a client who is the leader crashing and a follower client picking up the same work.
|
The goal of this mock worker is to simulate the behavior of a client who is the leader crashing and a follower client picking up the same work. |