Add a flag to denote that a server is disabled

A server is not normally disabled, but in the event of an RPC error, we want to mark a server as down to allow for fast failover to a different server.  This value must be an int in order to support atomic operations.

Additionally, this is the preliminary work required to bring up a server in a disabled state.  RPC health checks in the future could mark the server as alive, thereby creating an organic "slow start" feature for Consul.
This commit is contained in:
Sean Chittenden 2016-02-19 00:27:39 -08:00
parent 7de85906c1
commit 6bda2c007c
2 changed files with 26 additions and 4 deletions

View File

@ -23,7 +23,7 @@ import (
*/
var privateBlocks []*net.IPNet
// serverparts is used to return the parts of a server role
// serverParts is used to return the parts of a server role
type serverParts struct {
Name string
Datacenter string
@ -32,6 +32,11 @@ type serverParts struct {
Expect int
Version int
Addr net.Addr
// Disabled is a uint64 in order to support atomic integer
// operations. Zero means enabled, non-zero is the number of times
// this server has failed without being marked healthy.
Disabled uint64
}
func (s *serverParts) String() string {
@ -116,8 +121,8 @@ func CanServersUnderstandProtocol(members []serf.Member, version uint8) (bool, e
return (numServers > 0) && (numWhoGrok == numServers), nil
}
// Returns if a member is a consul server. Returns a bool,
// the datacenter, and the rpc port
// Returns true if a serf member is a consul server. Returns a bool and a
// pointer to the serverParts.
func isConsulServer(m serf.Member) (bool, *serverParts) {
if m.Tags["role"] != "consul" {
return false, nil
@ -125,6 +130,11 @@ func isConsulServer(m serf.Member) (bool, *serverParts) {
datacenter := m.Tags["dc"]
_, bootstrap := m.Tags["bootstrap"]
var disabled uint64 = 0
_, disabledStr := m.Tags["disabled"]
if disabledStr {
disabled = 1
}
expect := 0
expect_str, ok := m.Tags["expect"]
@ -158,6 +168,7 @@ func isConsulServer(m serf.Member) (bool, *serverParts) {
Expect: expect,
Addr: addr,
Version: vsn,
Disabled: disabled,
}
return true, parts
}

View File

@ -217,14 +217,24 @@ func TestIsConsulServer(t *testing.T) {
if parts.Bootstrap {
t.Fatalf("unexpected bootstrap")
}
if parts.Disabled > 0 {
t.Fatalf("unexpected disabled")
}
if parts.Expect != 0 {
t.Fatalf("bad: %v", parts.Expect)
}
m.Tags["bootstrap"] = "1"
m.Tags["disabled"] = "1"
valid, parts = isConsulServer(m)
if !valid || !parts.Bootstrap {
if !valid {
t.Fatalf("expected a valid consul server")
}
if !parts.Bootstrap {
t.Fatalf("expected bootstrap")
}
if parts.Disabled == 0 {
t.Fatalf("expected disabled")
}
if parts.Addr.String() != "127.0.0.1:10000" {
t.Fatalf("bad addr: %v", parts.Addr)
}
@ -233,6 +243,7 @@ func TestIsConsulServer(t *testing.T) {
}
m.Tags["expect"] = "3"
delete(m.Tags, "bootstrap")
delete(m.Tags, "disabled")
valid, parts = isConsulServer(m)
if !valid || parts.Expect != 3 {
t.Fatalf("bad: %v", parts.Expect)