Published on Jan 27 2012 in Java JBoss

Java hosting clients that use Tomcat and JBoss products can enable APR for their application server in our custom Java Control Panel. This gives most speedup to clients who use catch-all mapping and process all requests via application server instead of Apache or Nginx frontends.

JBoss Web uses the Apache Portable Runtime to provide superior scalability, performance, and better integration with native server technologies. The Apache Portable Runtime is a highly portable library that is at the heart of Apache HTTP Server 2.x. APR has many uses, including access to advanced IO functionality (such as sendfile, epoll, IPv6 and OpenSSL), OS level functionality (random number generation, system status, etc), and native process handling (shared memory, NT pipes and Unix sockets).

These features allow making JBoss Web a general purpose webserver, will enable much better integration with other native web technologies, and overall makes Java much more viable as a full fledged webserver platform rather than simply a backend focused technology.

There are 3 APR Connectors in JBoss Web: HTTP, HTTPS and AJP. Here goes the procedure that we tried and tested with our standard JBoss package. Our clients can turn on/off APR support via Java Control Panel (accessible from cPanel).

For the purpose of this tutorial we assume JBoss is installed in ~/appservers/jboss-as-web-7.0.2.Final. Download the latest native libraries in .tar.gz format for your machine architecture from http://jbossweb.jboss.org/downloads/jboss-native-2-0-10. With default setup you will see in ~/appservers/jboss-as-web-7.0.2.Final/standalone/log/server.log messages like:

15:47:47,232 INFO  [org.apache.catalina.core.AprLifecycleListener] (MSC service thread 1-4) The Apache 
Tomcat Native library which allows optimal performance in production environments was not found on 
the java.library.path: ...

Manual install of APR library in 64-bit environment

cd ~/appservers/jboss-as-web-7.0.2.Final/bin
wget http://downloads.jboss.org/jbossnative/2.0.10.GA/jboss-native-2.0.10-linux2-x64-ssl.tar.gz
tar xzf jboss-native-2.0.10-linux2-x64-ssl.tar.gz
rm jboss-native-2.0.10-linux2-x64-ssl.tar.gz
mkdir -p META-INF/lib/linux2
mv native META-INF/lib/linux2/x86_64

Optionally (as it works for us without it) you may append -Djava.library.path=/home/jbossjvm/appservers/jboss-as-web-7.0.2.Final/bin/META-INF/lib/linux2/x86_64 to $JAVA_OPTS environment variable for example in ~/.bashrc or JBoss' standalone.conf.

JBoss 7 AS 7.1.0.CR1b Flux Capacitor contains updated jbossweb-7.0.7.Final.jar in ~/appservers/jboss-as-web-7.0.2.Final/modules/org/jboss/as/web/main comparing to jbossweb-7.0.1.Final.jar that was causing issues according to https://developer.jboss.org/wiki/UsingNativeLibrariesaprWithJBoss702

We have not seen the crashes mentioned in the above article while using both jbossweb-7.0.7.Final.jar and jbossweb-7.0.1.Final.jar. After JBoss restart you should not see the above warning about missing native library in server.log anymore. You can verify if the libtcnative library is loaded by java process. Get PID of your java process with jps or pidof java or ps x then run

lsof -p 6280 | grep tcnative
java 6280 jbossjvm mem REG 9,3 896875 36965936 .../bin/META-INF/lib/linux2/x86_64/libtcnative-1.so.0.1.22

or

pmap 6280 | grep tcnative
00002aaabc000000    128K r-x--  .../bin/META-INF/lib/linux2/x86_64/libtcnative-1.so.0.1.22
00002aaabc020000   1020K -----  .../bin/META-INF/lib/linux2/x86_64/libtcnative-1.so.0.1.22
00002aaabc11f000      8K rwx--  .../bin/META-INF/lib/linux2/x86_64/libtcnative-1.so.0.1.22

Enabling AJP Connector

Now we need to add and enable AJP connector in ~/appservers/jboss-as-web-7.0.2.Final/standalone/configuration/standalone.xml. To use AJP define a ajp connector in the web subsystem like:

<subsystem xmlns="urn:jboss:domain:web:1.0">
<connector name="http" protocol="HTTP/1.1" socket-binding="http"/>
<connector name="ajp" protocol="AJP/1.3" socket-binding="ajp"/>

Add ajp to the socket-binding-group like:

<socket-binding-group name="standard-sockets" default-interface="public">
    ....
    <socket-binding name="http" port="8080"/>
    <socket-binding name="ajp" port="8009"/>
    <socket-binding name="https" port="8443"/>

The port numbers are default ones. JVMHost clients can check correct port reserved for AJP in JCP panel. Restart JBoss, switch from mod_proxy to mod_jk or mod_proxy_ajp in JCP and access your JBoss.

Note: There were crashes reported on some platforms so you may want to run JMeter or other stress tool against your JBoss with APR/AJP enabled before going into production. https://issues.jboss.org/browse/JBWEB-201 https://developer.jboss.org/thread/172104?_sscc=t