Enforce cluster-level WLM request throttling (shared_limit) - #10
Conversation
| * version, otherwise a rolling upgrade with older-but-same-major data nodes would map buckets to nodes lacking the | ||
| * handler. (Tracked alongside the throttle-settings version-gate TODO.) | ||
| */ | ||
| public static final Version MIN_OWNER_VERSION = Version.V_3_7_0; |
There was a problem hiding this comment.
Change to latest version when merging to main
3926b0c to
adc8a63
Compare
LilyCaroline17
left a comment
There was a problem hiding this comment.
One other thing, for the SharedThrottleTracker, we have leasesByBucket which an outer map (per bucket) of inner maps (leases per bucket) so the inner map is bounded by shared_limit per bucket, but the outer map isn't bounded by anything so it could potentially become really big. For example, if the throttling is done by username, and there's a large number of simultaneous requests from users, the owner node will have a large number of entries in that outer map all on that one node. Would it make sense to create a bound per buckets per owner, tracking this information, or figuring out a way to spread that load?
Signed-off-by: David Zane <davizane@amazon.com>
adc8a63 to
9be1a3f
Compare
You're right that In the worst case, a domain could have up to 100 WLM groups (current limit) and 100,000 unique users, which is 100 × 100,000 = 10,000,000 possible buckets. That sounds like a lot, but the real constraint is how many of those buckets have in-flight searches at any given moment — only those hold an entry in In-flight searches are bounded by the search thread pool + queue (~1050 per node), so a node's map can't exceed its in-flight capacity no matter how many users/groups exist. On top of that, buckets are distributed across all data nodes by a consistent-hash ring: bucket X's cluster-level permits live on a single owner node Y (while nodes are stable), so each node tracks just its ~1/N share, not every bucket. |
Adds cluster-level request throttling to Workload Management via a new
shared_limiton a workload group. Builds on the node-level (node_limit) tier: a request is admitted locally first, and only on local exhaustion does it consult a shared, cluster-wide pool.Total ceiling =
node_limit × N + shared_limit.How it works
Tests
WlmClusterThrottlingITverifies the cluster-wide ceiling holds across multiple coordinators.Latency benchmark
Measured on a local 3-node cluster (
match_allsearches round-robined across all 3 coordinators, tagged via theworkloadGroupIdheader,attribute=group). Limits set far above peak concurrency so nothing is rejected — this isolates the admission-path overhead on admitted requests (0 throttled / 0 rejected across 16k completions). Median of 3 runs; latencies in ms.Node-only throttling is effectively free (within noise); shared-only adds ~0.6ms mean / ~2.7ms p99-under-burst for the cross-node acquire round-trip.