Serving up Glassfish 3.x from port 80/443 via NAT

After a good amount of load testing and tinkering, I’ve found that mod_jk does not play too well with oracle glassfish 3, at least not in the environment/configuration I’m using. After about 30% of requests timing out in a web app which was using JSF 2 (facelets core, tomahawk, and primefaces) / EJB 3.1 / JPA 2 on top of oracle 11g db (tuned caching, native queries, etc…), the culprit turned out to be mod_jk misbehaving. After diagnosing the issue, I’ve decided to leave the httpd< -->mod_jk< -->glassfish setup behind, and KISS.

I’ve turned off httpd, forwarded all requests using NAT in iptables (just tcp, didn’t need udp, but NAT-ing udp as well doesn’t hurt anything) from port 80 to the port I’ve configured the glassfish http listener to listen on (standard is 8080, probably not a bad idea to change this and NAT to that port). Of course, the glassfish http listener’s port had to be configured to accept connections via iptables.

Glassfish uses grizzly as an http server (impl. uses java NIO under the hood), after performance testing and tuning this a bit… viola, timed out requests gone. With a bit more tuning, of JVM params, resource pool sizes, listener threads, application profiling/monitoring, etc., the app server became much snappier at serving requests. ) you may run two separate domains for glassfish with a more imaginative listener configuration.

Sample commands to achieve NAT using iptables for CentOS/RHEL 5.x:

# iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
# iptables -A PREROUTING -t nat -i eth0 -p udp --dport 80 -j REDIRECT --to-port 8080

# service iptables save
# vi /etc/sysconfig/iptables
-A RH-Firewall-1-INPUT -p tcp -m state --state NEW -m tcp --dport 8080 -j ACCEPT
# service iptables restart

Similarly, you may replace 80 with 443 and 8080 with 8181 to NAT https.