moby/daemon/discovery_test.go
Madhu Venugopal 2efdb8cbf5 Make discovery ttl and heartbeat configurable
Docker daemon uses kv-store as the host-discovery backend.
Discovery module tracks the liveness of a node through a simple
keepalive mechanism.  The keepalive mechanism depends on every
node performing heartbeat by registering itself with the discovery
module (via KV-Store Put operation). And for every Put operation,
the discovery module in all other nodes will receive a Watch
notification. That keeps the node alive.
Any node that fails to register itself within the TTL timer is
considered dead and removed from the discovery database.

The default timer (heartbeat = 20 seconds & ttl = 60 seconds)
works fine for small clusters.  But for large clusters, these
default timers are extremely aggressive and that causes high CPU
& most of the processing is spent managing the node discovery
and that impacts normal daemon operation.

Hence we need a way to make the discovery ttl and heartbeat
configurable.  As the cluster size grows, the user can change
these timers to make sure the daemon scales.

Signed-off-by: Madhu Venugopal <madhu@docker.com>
2015-11-25 06:51:55 -08:00

91 lines
2.4 KiB
Go

package daemon
import (
"testing"
"time"
)
func TestDiscoveryOpts(t *testing.T) {
clusterOpts := map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "5"}
heartbeat, ttl, err := discoveryOpts(clusterOpts)
if err == nil {
t.Fatalf("discovery.ttl < discovery.heartbeat must fail")
}
clusterOpts = map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "10"}
heartbeat, ttl, err = discoveryOpts(clusterOpts)
if err == nil {
t.Fatalf("discovery.ttl == discovery.heartbeat must fail")
}
clusterOpts = map[string]string{"discovery.heartbeat": "invalid"}
heartbeat, ttl, err = discoveryOpts(clusterOpts)
if err == nil {
t.Fatalf("invalid discovery.heartbeat must fail")
}
clusterOpts = map[string]string{"discovery.ttl": "invalid"}
heartbeat, ttl, err = discoveryOpts(clusterOpts)
if err == nil {
t.Fatalf("invalid discovery.ttl must fail")
}
clusterOpts = map[string]string{"discovery.heartbeat": "10", "discovery.ttl": "20"}
heartbeat, ttl, err = discoveryOpts(clusterOpts)
if err != nil {
t.Fatal(err)
}
if heartbeat != 10*time.Second {
t.Fatalf("Heatbeat - Expected : %v, Actual : %v", 10*time.Second, heartbeat)
}
if ttl != 20*time.Second {
t.Fatalf("TTL - Expected : %v, Actual : %v", 20*time.Second, ttl)
}
clusterOpts = map[string]string{"discovery.heartbeat": "10"}
heartbeat, ttl, err = discoveryOpts(clusterOpts)
if err != nil {
t.Fatal(err)
}
if heartbeat != 10*time.Second {
t.Fatalf("Heatbeat - Expected : %v, Actual : %v", 10*time.Second, heartbeat)
}
expected := 10 * defaultDiscoveryTTLFactor * time.Second
if ttl != expected {
t.Fatalf("TTL - Expected : %v, Actual : %v", expected, ttl)
}
clusterOpts = map[string]string{"discovery.ttl": "30"}
heartbeat, ttl, err = discoveryOpts(clusterOpts)
if err != nil {
t.Fatal(err)
}
if ttl != 30*time.Second {
t.Fatalf("TTL - Expected : %v, Actual : %v", 30*time.Second, ttl)
}
expected = 30 * time.Second / defaultDiscoveryTTLFactor
if heartbeat != expected {
t.Fatalf("Heatbeat - Expected : %v, Actual : %v", expected, heartbeat)
}
clusterOpts = map[string]string{}
heartbeat, ttl, err = discoveryOpts(clusterOpts)
if err != nil {
t.Fatal(err)
}
if heartbeat != defaultDiscoveryHeartbeat {
t.Fatalf("Heatbeat - Expected : %v, Actual : %v", defaultDiscoveryHeartbeat, heartbeat)
}
expected = defaultDiscoveryHeartbeat * defaultDiscoveryTTLFactor
if ttl != expected {
t.Fatalf("TTL - Expected : %v, Actual : %v", expected, ttl)
}
}