We use apache webserver as a frontend to tomcat and had been using mod_jk for years. When we transitioned from Apache 2.0 to 2.2 we decided to try using mod_proxy_ajp because it seemed to be the direction most blogs/stackoverflow posts were recommending these days. Not to mention I was unable to find mod_jk binaries for windows. (I later found windows binaries for mod_jk (32-bit and 64-bit) here:
What we found is that if you have a high performance web application. You’re absolutely going to want to use mod_jk. I think this point is greatly understated on many other comparisons.
I did a quick and dirty performance test… using windows performance monitor (heh). It has a neat feature that lets you calculate the average cpu over time which is pretty helpful. Ironically, windows performance monitoring consumes an insane amount of cpu itself… but I digress.
Test #1 - CPU Utilization:
Win2008 R2, Apache 2.2.22, VMware
Generated a load of 400 requests/second (using a proprietary tool I wrote that simulates our application)
I let performance monitor run and calculate the average load consumed by each process over that 2 minute time period.
In between tests, all I did was modify the httpd.conf to change a few JkMount (mod_jk) statements to ProxyPassMatch (mod_proxy_ajp) statements. Didn’t restart tomcat.
Here are the results:
|Average CPU %||Apache Webserver||Apache Tomcat||Total|
|Mod Proxy AJP||18.49||25.94||44.43%|
For the same load, our application used half as much CPU when using Mod JK!
Test #2 - Max Throughput Tests
After my initial post, I decided to go back and do another test using apache JMeter. Click the thumbnail below to see the full results marked up with comments. Essentially though, with mod_jk I was able to get 1400/sec and with mod_proxy_ajp I’d max out at about 900 (but with errors also).
Errors when using Mod Proxy AJP
As we ramped up number of active users we’d get errors much sooner with mod_proxy_ajp. This is definitely more of an issue on Windows xp and Windows 2003 server machines then it was 2008 R2 or windows 7 box. I don’t recall off hand all the things we tried to fix this. I’m pretty sure we tried increasing ThreadsPerChild and other settings and it didn’t really help the problem at all. I also remember we tried turning on mod_status and from the looks of things it did not appear that we were running out of workers. It just didn’t add up. But, afraid I didn’t investigate too much longer as the performance reasons alone were reason enough for me to switch back to Mod JK. Perhaps someone else can shed more light on this.
This is the error that would show up in apache-error.log when using mod_proxy_ajp under high load:
Windows 2008 R2 (with apache 2.2.22):
[Mon Feb 27 15:28:30 2012] [error] proxy: AJP: failed to make connection to backend: localhost
[Mon Feb 27 15:28:30 2012] [error] (OS 10055)An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full. : proxy: AJP: attempt to connect to 127.0.0.1:8029 (*) failed
Another error message we saw is below. I’m not sure if we got this error message only when we tested against windows XP/server 2003 boxes or if it was because we had Apache 2.2.21 on them.
[Tue Feb 07 14:48:00 2012] [warn] Server ran out of threads to serve requests. Consider raising the ThreadsPerChild setting
[Tue Feb 07 15:05:13 2012] [error] (OS 10061)No connection could be made because the target machine actively refused it. : proxy: AJP: attempt to connect to 127.0.0.1:8029 (*) failed
[Tue Feb 07 15:05:13 2012] [error] proxy: AJP: failed to make connection to backend: localhost
httpd.conf for mod_jk
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
# JkOptions indicate to send SSL KEY SIZE,
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat set the request format
#JkRequestLogFormat will print an entry such as: [Tue Feb 10 13:13:38 2009] worker2 tb1.alertustech.com 0.032000 -- for each jsp request.
#JkRequestLogFormat "%w %V %T"
# The following mount points forward requests matching the URL sequence to an application server.
JkMount /mywebapp/get*.jsp worker2
httpd.conf for mod_proxy_ajp
ProxyPassMatch \/(mywebapp\/get.*\.jsp)$ ajp://localhost:8029/$1