Repository navigation
mod_proxy: Add a per-worker maxbusy limit on concurrent requests, glo… - #857
Open
arturobernalg wants to merge 1 commit into
Open
arturobernalg wants to merge 1 commit into
arturobernalg wants to merge 1 commit into
Conversation
…bal across children
arturobernalg
force-pushed
the
proxy-worker-maxbusy
branch
from
October 17, 2026 08:59
81680d2 to
4a77931
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
max=on a BalancerMember only bounds the per-child connection pool; nothing today provides a process-global limit on concurrently active requests to a backend, so under multiple children/threads a backend can receive far more concurrent requests than an admin configuringmax=Nwould expect.This adds
maxbusy=NtoBalancerMember: a hard cap on requests concurrently active against that specific member, counted across all child processes and surviving a graceful restart. 0 (the default) keeps current behavior.Design: a new admission table is kept separate from
worker->s->busy(which stays exactly as it is today, including its use bybybusynessand its reset() semantics) and separate fromproxy_worker_shared, which is per-restart-generation shared memory and so cannot hold live cross-generation state. The table lives in anapr_shmretained viaap_retained_data_get()/_create()(already used in this file forproxy_start_time), owned by the parent process, so it survives both a graceful restart and the unload/reload of mod_proxy.so that a graceful restart causes. Every statically configuredmaxbusymember is known bypost_configtime (the balancer-manager dynamic-worker form does not exposemaxbusy), so every admission slot is pre-registered once inmod_proxy_balancer'spost_config, afterbalancer->s->snameis final; the request path only ever looks up an existing slot and does an atomic CAS reserve/release, never creating one, so there is no creation race between processes or generations. A saturated member is treated like a disabled/error member for selection purposes (sticky redirect, hot spares, balancertimeout), not marked in error itself. Reservation release is a separate cleanup from the busy-count cleanup, run immediately whenproxy_handler()abandons a worker for a failover attempt, rather than only at the end of the whole request.Tested manually with real multi-child builds (prefork/worker/event), real graceful restarts with in-flight requests,
BalancerPersiston and off, sticky/redirect/hot-spare/standby topologies, failover chains, and backend HTTP/2 and WebSocket/tunnel traffic. Addedtest/modules/proxy/test_07_maxbusy.py.MMN bumped to 20211221.34 for the new
proxy_worker_shared::maxbusyfield and the newap_proxy_*exports.This PR does not report or address a security vulnerability, follows the httpd style guide, uses an empty
APLOGNO()tag for its new log messages, includes achanges-entries/*.txtfile, and includes pyhttpd test cases intest/modules/proxy/.