forked from hashicorp/nomad
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR is implementing the leadership transfer extension described in the thesis chap 3.10. Background: Consul is performing some setup after acquiring leadership. It is possible that the setup fails, but there is no good way to step down as a leader. It is possible to use DemoteVoter as show in hashicorp/consul#5247, but this is suboptimal because it relies on Consul's autopilot to promote the old leader to a voter again. Since there is a perfectly fine way described in the thesis: leadership transfer extension, we decided to implement that instead. Doing it this way also helps other teams, since it is more generic. The necessary steps to perform are: 1. Leader picks target to transition to 2. Leader stops accepting client requests 3. Leader makes sure to replicate logs to the target 4. Leader sends TimeoutNow RPC request 5. Target receives TimeoutNow request, which triggers an election 6a. If the election is successful, a message with the new term will make the old leader step down 6b. if after electiontimeout the leadership transfer did not complete, the old leader resumes operation Resources: https://github.com/etcd-io/etcd/tree/master/raft
- Loading branch information
1 parent
2c55169
commit eba8343
Showing
12 changed files
with
835 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package fuzzy | ||
|
||
import ( | ||
"math/rand" | ||
"testing" | ||
"time" | ||
|
||
"github.com/hashicorp/raft" | ||
) | ||
|
||
// 5 node cluster | ||
func TestRaft_FuzzyLeadershipTransfer(t *testing.T) { | ||
cluster := newRaftCluster(t, testLogWriter, "lt", 5, nil) | ||
r := rand.New(rand.NewSource(time.Now().UnixNano())) | ||
|
||
s := newApplySource("LeadershipTransfer") | ||
data := cluster.generateNApplies(s, uint(r.Intn(10000))) | ||
futures := cluster.sendNApplies(time.Minute, data) | ||
cluster.leadershipTransfer(time.Minute) | ||
|
||
data = cluster.generateNApplies(s, uint(r.Intn(10000))) | ||
futures = append(futures, cluster.sendNApplies(time.Minute, data)...) | ||
cluster.leadershipTransfer(time.Minute) | ||
|
||
data = cluster.generateNApplies(s, uint(r.Intn(10000))) | ||
futures = append(futures, cluster.sendNApplies(time.Minute, data)...) | ||
cluster.leadershipTransfer(time.Minute) | ||
|
||
data = cluster.generateNApplies(s, uint(r.Intn(10000))) | ||
futures = append(futures, cluster.sendNApplies(time.Minute, data)...) | ||
|
||
ac := cluster.checkApplyFutures(futures) | ||
|
||
cluster.Stop(t, time.Minute) | ||
cluster.VerifyLog(t, ac) | ||
cluster.VerifyFSM(t) | ||
} | ||
|
||
type LeadershipTransferMode int | ||
|
||
type LeadershipTransfer struct { | ||
verifier appendEntriesVerifier | ||
slowNodes map[string]bool | ||
delayMin time.Duration | ||
delayMax time.Duration | ||
mode LeadershipTransferMode | ||
} | ||
|
||
func (lt *LeadershipTransfer) Report(t *testing.T) { | ||
lt.verifier.Report(t) | ||
} | ||
|
||
func (lt *LeadershipTransfer) PreRPC(s, t string, r *raft.RPC) error { | ||
return nil | ||
} | ||
|
||
func (lt *LeadershipTransfer) nap() { | ||
d := lt.delayMin + time.Duration(rand.Int63n((lt.delayMax - lt.delayMin).Nanoseconds())) | ||
time.Sleep(d) | ||
} | ||
|
||
func (lt *LeadershipTransfer) PostRPC(src, target string, r *raft.RPC, res *raft.RPCResponse) error { | ||
return nil | ||
} | ||
|
||
func (lt *LeadershipTransfer) PreRequestVote(src, target string, v *raft.RequestVoteRequest) (*raft.RequestVoteResponse, error) { | ||
return nil, nil | ||
} | ||
|
||
func (lt *LeadershipTransfer) PreAppendEntries(src, target string, v *raft.AppendEntriesRequest) (*raft.AppendEntriesResponse, error) { | ||
lt.verifier.PreAppendEntries(src, target, v) | ||
return nil, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.