mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 10:25:42 +03:00
rpcproxy is refactored into serverlist which prioritizes good servers over servers in a remote DC or who have had a failure. Registration, heartbeating, and alloc status updating will retry faster when new servers are discovered. Consul discovery will be retried more quickly when no servers are available (eg on startup or an outage).
118 lines
3.2 KiB
Go
118 lines
3.2 KiB
Go
package client
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestServerList(t *testing.T) {
|
|
s := newServerList()
|
|
|
|
// New lists should be empty
|
|
if e := s.all(); len(e) != 0 {
|
|
t.Fatalf("expected empty list to return an empty list, but received: %+q", e)
|
|
}
|
|
|
|
mklist := func() endpoints {
|
|
return endpoints{
|
|
&endpoint{"b", nil, 1},
|
|
&endpoint{"c", nil, 1},
|
|
&endpoint{"g", nil, 2},
|
|
&endpoint{"d", nil, 1},
|
|
&endpoint{"e", nil, 1},
|
|
&endpoint{"f", nil, 1},
|
|
&endpoint{"h", nil, 2},
|
|
&endpoint{"a", nil, 0},
|
|
}
|
|
}
|
|
s.set(mklist())
|
|
|
|
orig := mklist()
|
|
all := s.all()
|
|
if len(all) != len(orig) {
|
|
t.Fatalf("expected %d endpoints but only have %d", len(orig), len(all))
|
|
}
|
|
|
|
// Assert list is properly randomized+sorted
|
|
for i, pri := range []int{0, 1, 1, 1, 1, 1, 2, 2} {
|
|
if all[i].priority != pri {
|
|
t.Errorf("expected endpoint %d (%+q) to be priority %d", i, all[i], pri)
|
|
}
|
|
}
|
|
|
|
// Subsequent sets should reshuffle (try multiple times as they may
|
|
// shuffle in the same order)
|
|
tries := 0
|
|
max := 3
|
|
for ; tries < max; tries++ {
|
|
if s.all().String() == s.all().String() {
|
|
// eek, matched; try again in case we just got unlucky
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
if tries == max {
|
|
t.Fatalf("after %d attempts servers were still not random reshuffled", tries)
|
|
}
|
|
|
|
// Mark an endpoint as failed enough that it should be at the end of the list
|
|
sa := &endpoint{"a", nil, 0}
|
|
s.failed(sa)
|
|
s.failed(sa)
|
|
s.failed(sa)
|
|
all2 := s.all()
|
|
if len(all2) != len(orig) {
|
|
t.Fatalf("marking should not have changed list length")
|
|
}
|
|
if all2[len(all)-1].name != sa.name {
|
|
t.Fatalf("failed endpoint should be at end of list: %+q", all2)
|
|
}
|
|
|
|
// But if the bad endpoint succeeds even once it should be bumped to the top group
|
|
s.good(sa)
|
|
found := false
|
|
for _, e := range s.all() {
|
|
if e.name == sa.name {
|
|
if e.priority != 0 {
|
|
t.Fatalf("server newly marked good should have highest priority")
|
|
}
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
t.Fatalf("what happened to endpoint A?!")
|
|
}
|
|
}
|
|
|
|
// TestClient_ServerList tests client methods that interact with the internal
|
|
// nomad server list.
|
|
func TestClient_ServerList(t *testing.T) {
|
|
// manually create a mostly empty client to avoid spinning up a ton of
|
|
// goroutines that complicate testing
|
|
client := Client{servers: newServerList(), logger: log.New(os.Stderr, "", log.Ltime|log.Lshortfile)}
|
|
|
|
if s := client.GetServers(); len(s) != 0 {
|
|
t.Fatalf("expected server lit to be empty but found: %+q", s)
|
|
}
|
|
if err := client.SetServers(nil); err != noServers {
|
|
t.Fatalf("expected setting an empty list to return a 'no servers' error but received %v", err)
|
|
}
|
|
if err := client.SetServers([]string{"not-a-real-domain.fake"}); err == nil {
|
|
t.Fatalf("expected setting a bad server to return an error")
|
|
}
|
|
if err := client.SetServers([]string{"bad.fake", "127.0.0.1:1234", "127.0.0.1"}); err != nil {
|
|
t.Fatalf("expected setting at least one good server to succeed but received: %v", err)
|
|
}
|
|
s := client.GetServers()
|
|
if len(s) != 2 {
|
|
t.Fatalf("expected 2 servers but received: %+q", s)
|
|
}
|
|
for _, host := range s {
|
|
if !strings.HasPrefix(host, "127.0.0.1:") {
|
|
t.Errorf("expected both servers to be localhost and include port but found: %s", host)
|
|
}
|
|
}
|
|
}
|