@marcel91200 / caddy Mirror · read-only / commits / d4a7d89f
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 13, 09:15 UTC

reverseproxy: Improve hostByHashing distribution (#5229)

* If upstreams are all using same host but with different ports ie: foobar:4001 foobar:4002 foobar:4003 ... Because fnv-1a has not a good enough avalanche effect Then the hostByHashing result is not well balanced over all upstreams As last byte FNV input tend to affect few bits, the idea is to change the concatenation order between the key and the upstream strings So the upstream last byte have more impact on hash diffusion

Alban Lecocq committed Dec 5, 2022 at 19:28 UTC d4a7d89f564234e44012a763cc28c5a3991bd98e
2 files changed +23 -23
modules/caddyhttp/reverseproxy/selectionpolicies.go
+1 -1
@@ -528,7 +528,7 @@ func hostByHashing(pool []*Upstream, s string) *Upstream {
528 if !up.Available() {
529 continue
530 }
531 - h := hash(s + up.String()) // important to hash key and server together
531 + h := hash(up.String() + s) // important to hash key and server together
532 if h > highestHash {
533 highestHash = h
534 upstream = up
modules/caddyhttp/reverseproxy/selectionpolicies_test.go
+22 -22
@@ -95,18 +95,18 @@ func TestIPHashPolicy(t *testing.T) {
95 // We should be able to predict where every request is routed.
96 req.RemoteAddr = "172.0.0.1:80"
97 h := ipHash.Select(pool, req, nil)
98 - if h != pool[0] {
99 - t.Error("Expected ip hash policy host to be the first host.")
98 + if h != pool[1] {
99 + t.Error("Expected ip hash policy host to be the second host.")
100 }
101 req.RemoteAddr = "172.0.0.2:80"
102 h = ipHash.Select(pool, req, nil)
103 - if h != pool[0] {
104 - t.Error("Expected ip hash policy host to be the first host.")
103 + if h != pool[1] {
104 + t.Error("Expected ip hash policy host to be the second host.")
105 }
106 req.RemoteAddr = "172.0.0.3:80"
107 h = ipHash.Select(pool, req, nil)
108 - if h != pool[2] {
109 - t.Error("Expected ip hash policy host to be the third host.")
108 + if h != pool[1] {
109 + t.Error("Expected ip hash policy host to be the second host.")
110 }
111 req.RemoteAddr = "172.0.0.4:80"
112 h = ipHash.Select(pool, req, nil)
@@ -117,18 +117,18 @@ func TestIPHashPolicy(t *testing.T) {
117 // we should get the same results without a port
118 req.RemoteAddr = "172.0.0.1"
119 h = ipHash.Select(pool, req, nil)
120 - if h != pool[0] {
121 - t.Error("Expected ip hash policy host to be the first host.")
120 + if h != pool[1] {
121 + t.Error("Expected ip hash policy host to be the second host.")
122 }
123 req.RemoteAddr = "172.0.0.2"
124 h = ipHash.Select(pool, req, nil)
125 - if h != pool[0] {
126 - t.Error("Expected ip hash policy host to be the first host.")
125 + if h != pool[1] {
126 + t.Error("Expected ip hash policy host to be the second host.")
127 }
128 req.RemoteAddr = "172.0.0.3"
129 h = ipHash.Select(pool, req, nil)
130 - if h != pool[2] {
131 - t.Error("Expected ip hash policy host to be the third host.")
130 + if h != pool[1] {
131 + t.Error("Expected ip hash policy host to be the second host.")
132 }
133 req.RemoteAddr = "172.0.0.4"
134 h = ipHash.Select(pool, req, nil)
@@ -141,8 +141,8 @@ func TestIPHashPolicy(t *testing.T) {
141 req.RemoteAddr = "172.0.0.4"
142 pool[1].setHealthy(false)
143 h = ipHash.Select(pool, req, nil)
144 - if h != pool[2] {
145 - t.Error("Expected ip hash policy host to be the third host.")
144 + if h != pool[0] {
145 + t.Error("Expected ip hash policy host to be the first host.")
146 }
147
148 req.RemoteAddr = "172.0.0.2"
@@ -172,8 +172,8 @@ func TestIPHashPolicy(t *testing.T) {
172 }
173 req.RemoteAddr = "172.0.0.1:80"
174 h = ipHash.Select(pool, req, nil)
175 - if h != pool[1] {
176 - t.Error("Expected ip hash policy host to be the second host.")
175 + if h != pool[0] {
176 + t.Error("Expected ip hash policy host to be the first host.")
177 }
178 req.RemoteAddr = "172.0.0.2:80"
179 h = ipHash.Select(pool, req, nil)
@@ -182,8 +182,8 @@ func TestIPHashPolicy(t *testing.T) {
182 }
183 req.RemoteAddr = "172.0.0.3:80"
184 h = ipHash.Select(pool, req, nil)
185 - if h != pool[1] {
186 - t.Error("Expected ip hash policy host to be the second host.")
185 + if h != pool[0] {
186 + t.Error("Expected ip hash policy host to be the first host.")
187 }
188 req.RemoteAddr = "172.0.0.4:80"
189 h = ipHash.Select(pool, req, nil)
@@ -252,8 +252,8 @@ func TestURIHashPolicy(t *testing.T) {
252
253 request := httptest.NewRequest(http.MethodGet, "/test", nil)
254 h := uriPolicy.Select(pool, request, nil)
255 - if h != pool[2] {
256 - t.Error("Expected uri policy host to be the third host.")
255 + if h != pool[1] {
256 + t.Error("Expected uri policy host to be the second host.")
257 }
258
259 pool[2].setHealthy(false)
@@ -264,8 +264,8 @@ func TestURIHashPolicy(t *testing.T) {
264
265 request = httptest.NewRequest(http.MethodGet, "/test_2", nil)
266 h = uriPolicy.Select(pool, request, nil)
267 - if h != pool[1] {
268 - t.Error("Expected uri policy host to be the second host.")
267 + if h != pool[0] {
268 + t.Error("Expected uri policy host to be the first host.")
269 }
270
271 // We should be able to resize the host pool and still be able to predict