I have a fairly standard setup where a front-end Apache server forwards requests to Tomcat through mod_proxy/AJP. How can I setup Apache/mod_proxy so it only forwards at most N (say, N=4) concurrent requests to Tomcat? Other concurrent requests coming into Apache should not be rejected, and should instead be queued to later be sent to Tomcat.
PS 1: Note that this is something you can do this at Tomcat level with the maxThreads
attribute, but I prefer to handle this at the Apache level.
PS 2: I see that Apache has a MaxClients configuration, which seems to be doing what I am looking for. But it is not clear to me how to have a MaxClient per server mod_proxy forwards to, rather than MaxClient per Apache. I.e. if Apache forward requests to a cluster of 4 Tomcat machine, I'd like Apache to limit the number of concurrent requests forwarded to any given Tomcat to N (say, N=4).
The solutions is mod_proxy by adding parameters to ProxyPass directives. What you want to set is probably the max. This however will throw an error instantly and not queue your requests when you hit the max.
If you really want to queue you have to use also mod_proxy_balancer. For example allow maximum 4 connections:
ProxyPass / balancer://appservers/ stickysession=JSESSIONID|jsessionid nofailover=On
<Proxy balancer://appservers>
BalancerMember ajp://192.168.0.100:8009 max=4
BalancerMember ajp://192.168.0.101:8009 max=4
BalancerMember ajp://192.168.0.102:8009 max=4
BalancerMember ajp://192.168.0.103:8009 max=4
</Proxy>
Unfortunately, with in Apache, the value of max
is per process. So, you can only effectively limit the number of connections to your back-end servers if Apache has one process and uses threads instead of processes to handle multiple connections, which depends on what MPM is being used by Apache:
On UNIX, if you're using the Apache that came with your OS, unfortunately there is a good chance you have prefork MPM Apache, which creates one process per request, and with which the max parameter wouldn't work:
apachectl -l
.worker.c
or event.c
, then you are almost good: you now just need to make sure that Apache creates only one process. For this, set ThreadsPerChild
and MaxClients
to the same value, which will be the total number of concurrent connections your Apache will be able to process. Also set ServerLimit
to 1.prefork.c
, then you first need to replace your Apache with the worker or event MPM Apache. You can do so by either recompiling Apache yourself (the MPM is not a run-time configuration parameter), or getting a existing package for your platform. Then, go to step two.