Add healthcheck ordering to simple failover mode (#38)
* add healthcheck to simple failover * update comment * update comment * add another test
This commit is contained in:
parent
0fb094feb4
commit
ba221ab80f
@ -989,13 +989,21 @@ func weightedShuffle(backends []*Backend) {
|
|||||||
func (bg *BackendGroup) orderedBackendsForRequest() []*Backend {
|
func (bg *BackendGroup) orderedBackendsForRequest() []*Backend {
|
||||||
if bg.Consensus != nil {
|
if bg.Consensus != nil {
|
||||||
return bg.loadBalancedConsensusGroup()
|
return bg.loadBalancedConsensusGroup()
|
||||||
} else if bg.WeightedRouting {
|
|
||||||
result := make([]*Backend, len(bg.Backends))
|
|
||||||
copy(result, bg.Backends)
|
|
||||||
weightedShuffle(result)
|
|
||||||
return result
|
|
||||||
} else {
|
} else {
|
||||||
return bg.Backends
|
healthy := make([]*Backend, 0, len(bg.Backends))
|
||||||
|
unhealthy := make([]*Backend, 0, len(bg.Backends))
|
||||||
|
for _, be := range bg.Backends {
|
||||||
|
if be.IsHealthy() {
|
||||||
|
healthy = append(healthy, be)
|
||||||
|
} else {
|
||||||
|
unhealthy = append(unhealthy, be)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bg.WeightedRouting {
|
||||||
|
weightedShuffle(healthy)
|
||||||
|
weightedShuffle(unhealthy)
|
||||||
|
}
|
||||||
|
return append(healthy, unhealthy...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,52 @@ func TestFailover(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the bad endpoint has had 10 requests with 8 error (3xx/4xx/5xx) responses, it should be marked as unhealthy and deprioritized
|
||||||
|
t.Run("bad endpoint marked as unhealthy", func(t *testing.T) {
|
||||||
|
res, statusCode, err := client.SendRPC("eth_chainId", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 200, statusCode)
|
||||||
|
RequireEqualJSON(t, []byte(goodResponse), res)
|
||||||
|
require.Equal(t, 1, len(goodBackend.Requests()))
|
||||||
|
require.Equal(t, 0, len(badBackend.Requests())) // bad backend is not called anymore
|
||||||
|
goodBackend.Reset()
|
||||||
|
badBackend.Reset()
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("bad endpoint is still called if good endpoint also went bad", func(t *testing.T) {
|
||||||
|
goodBackend.SetHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
_, _ = w.Write([]byte("[{}]"))
|
||||||
|
}))
|
||||||
|
badBackend.SetHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(503)
|
||||||
|
_, _ = w.Write([]byte(unexpectedResponse))
|
||||||
|
}))
|
||||||
|
res, statusCode, _ := client.SendRPC("eth_chainId", nil)
|
||||||
|
require.Equal(t, 503, statusCode)
|
||||||
|
RequireEqualJSON(t, []byte(noBackendsResponse), res) // return no backend available since both failed
|
||||||
|
require.Equal(t, 1, len(goodBackend.Requests()))
|
||||||
|
require.Equal(t, 1, len(badBackend.Requests())) // bad backend is still called
|
||||||
|
goodBackend.Reset()
|
||||||
|
badBackend.Reset()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFailoverMore(t *testing.T) {
|
||||||
|
goodBackend := NewMockBackend(BatchedResponseHandler(200, goodResponse))
|
||||||
|
defer goodBackend.Close()
|
||||||
|
badBackend := NewMockBackend(nil)
|
||||||
|
defer badBackend.Close()
|
||||||
|
|
||||||
|
require.NoError(t, os.Setenv("GOOD_BACKEND_RPC_URL", goodBackend.URL()))
|
||||||
|
require.NoError(t, os.Setenv("BAD_BACKEND_RPC_URL", badBackend.URL()))
|
||||||
|
|
||||||
|
config := ReadConfig("failover")
|
||||||
|
client := NewProxydClient("http://127.0.0.1:8545")
|
||||||
|
_, shutdown, err := proxyd.Start(config)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer shutdown()
|
||||||
|
|
||||||
t.Run("backend times out and falls back to another", func(t *testing.T) {
|
t.Run("backend times out and falls back to another", func(t *testing.T) {
|
||||||
badBackend.SetHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
badBackend.SetHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
Loading…
Reference in New Issue
Block a user