-
-
Notifications
You must be signed in to change notification settings - Fork 675
Feat/round robin pool #4650
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feat/round robin pool #4650
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4650 +/- ##
==========================================
- Coverage 92.86% 92.84% -0.02%
==========================================
Files 106 107 +1
Lines 33272 33411 +139
==========================================
+ Hits 30897 31020 +123
- Misses 2375 2391 +16 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| } | ||
| }) | ||
|
|
||
| test('basic get', async (t) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this implementation relies on the RoundRobin algorithm implemented, I'd suggest that tests also accounts for that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added verifies round-robin kGetDispatcher cycling algorithm to complement the round-robin wraps around correctly test
| return new Client(origin, opts) | ||
| } | ||
|
|
||
| class RoundRobinPool extends PoolBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we can also provide a similar approach to BalancedPool to account for faulty upstreams (Clients) that are misbehaving and possibly re-balance distribution accordingly to implementer options
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plus one for this. Would be happy to revisit and see what we can do
|
The reason the default is to always reuse the last use connection is to avoid the inherent risk of keep-alive race conditions. IMHO, this should take into account the keep alive timeout of the individual connection, and just skip "old" ones that are most likely to cause an ECONNRESET. If a connection is over 80% of its keepalive, it's probably better to leave it alone unless if there is a different option. This could also be handled in the client itself as it would benefit all pools tbh. Without that change, users of this would see an increase of ECONNRESET errors. I'm not sure how you guarantee that each connection actually goes to a different server. This seems unlikely, as it depends on the underneath load balancer algorithm. |
Do you refer to the
What option do you have in mind? The proposal SGTM 👍 |
|
@metcoder95 nevermind, we already have that logic: undici/lib/dispatcher/client-h1.js Line 592 in 6301265
|
mcollina
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
My question on how this guarantees round robin on the server stand.
|
You're correct, we only guarantee client-side connection distribution. Backend distribution depends on how the load balancer assigns TCP connections to backends. I initially tested this with a homespun TCP LB which assigned each new connection to backends in round-robin fashion, but if the LB assigns using session affinity for example, there's not a whole lot we can do. I added documentation explaining the caveat. Also open to other suggestions. |
metcoder95
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Rationale
Addresses #3648
Pool distributes load unevenly across connections when used with load-balanced endpoints (e.g., Kubernetes Services). It always selects the first available connection, causing some backend servers to be overused while others remain idle.
RoundRobinPool solves this by cycling through connections in a round-robin fashion, ensuring even distribution of requests across all backend servers.
Changes
Pool.jsdistributionRoundRobinPool.jsdistributionFeatures
RoundRobinPoolclass(lib/dispatcher/round-robin-pool.js)docs/docs/api/RoundRobinPool.md)Status