diff --git a/vendor/github.com/hashicorp/memberlist/config.go b/vendor/github.com/hashicorp/memberlist/config.go index 27a52ea561..498a62c548 100644 --- a/vendor/github.com/hashicorp/memberlist/config.go +++ b/vendor/github.com/hashicorp/memberlist/config.go @@ -126,8 +126,12 @@ type Config struct { // per GossipInterval. Increasing this number causes the gossip messages // to propagate across the cluster more quickly at the expense of // increased bandwidth. - GossipInterval time.Duration - GossipNodes int + // + // GossipToTheDeadTime is the interval after which a node has died that + // we will still try to gossip to it. This gives it a chance to refute. + GossipInterval time.Duration + GossipNodes int + GossipToTheDeadTime time.Duration // EnableCompression is used to control message compression. This can // be used to reduce bandwidth usage at the cost of slightly more CPU @@ -212,8 +216,9 @@ func DefaultLANConfig() *Config { DisableTcpPings: false, // TCP pings are safe, even with mixed versions AwarenessMaxMultiplier: 8, // Probe interval backs off to 8 seconds - GossipNodes: 3, // Gossip to 3 nodes - GossipInterval: 200 * time.Millisecond, // Gossip more rapidly + GossipNodes: 3, // Gossip to 3 nodes + GossipInterval: 200 * time.Millisecond, // Gossip more rapidly + GossipToTheDeadTime: 30 * time.Second, // Same as push/pull EnableCompression: true, // Enable compression by default @@ -238,6 +243,7 @@ func DefaultWANConfig() *Config { conf.ProbeInterval = 5 * time.Second conf.GossipNodes = 4 // Gossip less frequently, but to an additional node conf.GossipInterval = 500 * time.Millisecond + conf.GossipToTheDeadTime = 60 * time.Second return conf } @@ -254,6 +260,7 @@ func DefaultLocalConfig() *Config { conf.ProbeTimeout = 200 * time.Millisecond conf.ProbeInterval = time.Second conf.GossipInterval = 100 * time.Millisecond + conf.GossipToTheDeadTime = 15 * time.Second return conf } diff --git a/vendor/github.com/hashicorp/memberlist/state.go b/vendor/github.com/hashicorp/memberlist/state.go index d5d34e40d7..cc422bc1a3 100644 --- a/vendor/github.com/hashicorp/memberlist/state.go +++ b/vendor/github.com/hashicorp/memberlist/state.go @@ -310,8 +310,11 @@ func (m *Memberlist) probeNode(node *nodeState) { // Get some random live nodes. m.nodeLock.RLock() - excludes := []string{m.config.Name, node.Name} - kNodes := kRandomNodes(m.config.IndirectChecks, excludes, m.nodes) + kNodes := kRandomNodes(m.config.IndirectChecks, m.nodes, func(n *nodeState) bool { + return n.Name == m.config.Name || + n.Name == node.Name || + n.State != stateAlive + }) m.nodeLock.RUnlock() // Attempt an indirect ping. @@ -460,10 +463,24 @@ func (m *Memberlist) resetNodes() { func (m *Memberlist) gossip() { defer metrics.MeasureSince([]string{"memberlist", "gossip"}, time.Now()) - // Get some random live nodes + // Get some random live, suspect, or recently dead nodes m.nodeLock.RLock() - excludes := []string{m.config.Name} - kNodes := kRandomNodes(m.config.GossipNodes, excludes, m.nodes) + kNodes := kRandomNodes(m.config.GossipNodes, m.nodes, func(n *nodeState) bool { + if n.Name == m.config.Name { + return true + } + + switch n.State { + case stateAlive, stateSuspect: + return false + + case stateDead: + return time.Since(n.StateChange) > m.config.GossipToTheDeadTime + + default: + return true + } + }) m.nodeLock.RUnlock() // Compute the bytes available @@ -497,8 +514,10 @@ func (m *Memberlist) gossip() { func (m *Memberlist) pushPull() { // Get a random live node m.nodeLock.RLock() - excludes := []string{m.config.Name} - nodes := kRandomNodes(1, excludes, m.nodes) + nodes := kRandomNodes(1, m.nodes, func(n *nodeState) bool { + return n.Name == m.config.Name || + n.State != stateAlive + }) m.nodeLock.RUnlock() // If no nodes, bail diff --git a/vendor/github.com/hashicorp/memberlist/util.go b/vendor/github.com/hashicorp/memberlist/util.go index c082ec6904..a294c3034d 100644 --- a/vendor/github.com/hashicorp/memberlist/util.go +++ b/vendor/github.com/hashicorp/memberlist/util.go @@ -155,8 +155,9 @@ func randomOffset(n int) int { // suspicionTimeout computes the timeout that should be used when // a node is suspected func suspicionTimeout(suspicionMult, n int, interval time.Duration) time.Duration { - nodeScale := math.Ceil(math.Log10(float64(n + 1))) - timeout := time.Duration(suspicionMult) * time.Duration(nodeScale) * interval + nodeScale := math.Max(1.0, math.Log10(math.Max(1.0, float64(n)))) + // multiply by 1000 to keep some precision because time.Duration is an int64 type + timeout := time.Duration(suspicionMult) * time.Duration(nodeScale*1000) * interval / 1000 return timeout } @@ -207,9 +208,10 @@ func moveDeadNodes(nodes []*nodeState) int { return n - numDead } -// kRandomNodes is used to select up to k random nodes, excluding a given -// node and any non-alive nodes. It is possible that less than k nodes are returned. -func kRandomNodes(k int, excludes []string, nodes []*nodeState) []*nodeState { +// kRandomNodes is used to select up to k random nodes, excluding any nodes where +// the filter function returns true. It is possible that less than k nodes are +// returned. +func kRandomNodes(k int, nodes []*nodeState, filterFn func(*nodeState) bool) []*nodeState { n := len(nodes) kNodes := make([]*nodeState, 0, k) OUTER: @@ -221,16 +223,9 @@ OUTER: idx := randomOffset(n) node := nodes[idx] - // Exclude node if match - for _, exclude := range excludes { - if node.Name == exclude { - continue OUTER - } - } - - // Exclude if not alive - if node.State != stateAlive { - continue + // Give the filter a shot at it. + if filterFn != nil && filterFn(node) { + continue OUTER } // Check if we have this node already diff --git a/vendor/vendor.json b/vendor/vendor.json index d4c8b1cec5..b130ac2712 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -528,10 +528,10 @@ "revisionTime": "2015-06-09T07:04:31Z" }, { - "checksumSHA1": "F2jm1h5jRic/Q0e3UEk4aqzS7k0=", + "checksumSHA1": "hSoH77pX3FyU6kkYqOOYmf3r55Y=", "path": "github.com/hashicorp/memberlist", - "revision": "56f5fd70afa73f13bbe529192aeb3dc7bc4bc960", - "revisionTime": "2016-12-05T22:01:58Z" + "revision": "9800c50ab79c002353852a9b1095e9591b161513", + "revisionTime": "2016-12-13T23:44:46Z" }, { "checksumSHA1": "qnlqWJYV81ENr61SZk9c65R1mDo=",