@@ -58,6 +58,17 @@ func (h *HashBased) Next(attempt int) *Endpoint {
5858 return endpoint
5959 }
6060
61+ if len (h .pool .endpoints ) == 0 {
62+ h .logger .Warn ("hash-based-routing-pool-empty" , slog .String ("host" , h .pool .host ))
63+ return nil
64+ }
65+
66+ endpoint = h .getSingleEndpoint ()
67+ if endpoint != nil {
68+ h .lastEndpoint = endpoint
69+ return endpoint
70+ }
71+
6172 if h .pool .HashLookupTable == nil {
6273 h .logger .Error ("hash-based-routing-failed" , slog .String ("host" , h .pool .host ), log .ErrAttr (errors .New ("Lookup table is empty" )))
6374 return nil
@@ -89,11 +100,6 @@ func (h *HashBased) Next(attempt int) *Endpoint {
89100}
90101
91102func (h * HashBased ) findEndpoint (index uint64 , attempt int ) * Endpoint {
92- maxIterations := len (h .pool .endpoints )
93- if maxIterations == 0 {
94- return nil
95- }
96-
97103 // Ensure we don't exceed the lookup table size
98104 lookupTableSize := h .pool .HashLookupTable .GetLookupTableSize ()
99105
@@ -128,10 +134,9 @@ func (h *HashBased) findEndpoint(index uint64, attempt int) *Endpoint {
128134
129135 lastEndpointPrivateId = id
130136
131- e := endpointElem .endpoint
132- if h .pool .HashRoutingProperties .BalanceFactor <= 0 || ! h .isOverloaded (e ) {
137+ if h .pool .HashRoutingProperties .BalanceFactor <= 0 || ! h .isImbalancedOrOverloaded (endpointElem ) {
133138 h .lastLookupTableIndex = currentIndex
134- return e
139+ return endpointElem . endpoint
135140 }
136141
137142 currentIndex = (currentIndex + 1 ) % lookupTableSize
@@ -141,11 +146,12 @@ func (h *HashBased) findEndpoint(index uint64, attempt int) *Endpoint {
141146 return nil
142147}
143148
144- func (h * HashBased ) isOverloaded (e * Endpoint ) bool {
145- avgLoad := h .CalculateAverageLoad ()
149+ func (h * HashBased ) isImbalancedOrOverloaded (e * endpointElem ) bool {
150+ endpoint := e .endpoint
151+ avgNumberOfConnections := h .CalculateAverageNumberOfConnections ()
146152 balanceFactor := h .pool .HashRoutingProperties .BalanceFactor
147- if float64 (e .Stats .NumberConnections .Count ())/ avgLoad > balanceFactor {
148- h .logger .Info ("hash-based-routing-endpoint-overloaded" , slog .String ("host" , h .pool .host ), slog .String ("endpoint-id" , e .PrivateInstanceId ), slog .Int64 ("endpoint-connections" , e .Stats .NumberConnections .Count ()), slog .Float64 ("average-load" , avgLoad ))
153+ if avgNumberOfConnections == 0 || float64 (endpoint .Stats .NumberConnections .Count ())/ avgNumberOfConnections > balanceFactor || e . isOverloaded () {
154+ h .logger .Debug ("hash-based-routing-endpoint-overloaded" , slog .String ("host" , h .pool .host ), slog .String ("endpoint-id" , endpoint .PrivateInstanceId ), slog .Int64 ("endpoint-connections" , endpoint .Stats .NumberConnections .Count ()), slog .Float64 ("average-load" , avgNumberOfConnections ))
149155 return true
150156 }
151157 return false
@@ -203,17 +209,29 @@ func (h *HashBased) PostRequest(e *Endpoint) {
203209 e .Stats .NumberConnections .Decrement ()
204210}
205211
206- func (h * HashBased ) CalculateAverageLoad () float64 {
212+ func (h * HashBased ) CalculateAverageNumberOfConnections () float64 {
207213 if len (h .pool .endpoints ) == 0 {
208214 return 0
209215 }
210216
211- var currentInFlightRequestCount int64
217+ var totalConnections int64
212218 for _ , endpointElem := range h .pool .endpoints {
213219 endpointElem .RLock ()
214- currentInFlightRequestCount += endpointElem .endpoint .Stats .NumberConnections .Count ()
220+ totalConnections += endpointElem .endpoint .Stats .NumberConnections .Count ()
215221 endpointElem .RUnlock ()
216222 }
217223
218- return float64 (currentInFlightRequestCount ) / float64 (len (h .pool .endpoints ))
224+ return float64 (totalConnections ) / float64 (len (h .pool .endpoints ))
225+ }
226+
227+ func (h * HashBased ) getSingleEndpoint () * Endpoint {
228+ if len (h .pool .endpoints ) == 1 {
229+ e := h .pool .endpoints [0 ]
230+ if e .isOverloaded () {
231+ return nil
232+ }
233+
234+ return e .endpoint
235+ }
236+ return nil
219237}
0 commit comments