Serving QueueMetrics through Apache

We advise using a NGINX proxy instead - it’s easier to configure and maintain. See Serving QueueMetrics through a NGINX proxy.

You may want to serve QueueMetrics through an Apache front-end instead of using Tomcat natively. This is useful if:

  • You require better efficiency, so that static files are served natively without passing through Tomcat

  • You need to integrate Qm on a virtual server that offers other services, e.g. applications written in PHP/Perl/CGI

  • You need to serve QM on the public internet and want to use the security tools Apache offers.

Prerequisites

  • A working QueueMetrics instance

  • Apache 2.0 installed, with headers and compilation tools

Installing mod_jk

Download 'mod_jk' from the Apache Tomcat website; it will be in a file named e.g 'jakarta-tomcat-connectors-jk-1.2-src-current.tar.gz' .

Run the following commands:

tar zxvf jakarta-tomcat-connectors-jk-1.2-src-current.tar.gz
cd jk/native

Check where the 'apxs' command is by running 'locate apxs'. Default location is '/usr/sbin/apxs'.

Check that $CATALINA_HOME and $JAVA_HOME are defined; default values are '/usr/local/queuemetrics/tomcat' and '/usr/local/queuemetrics/java' respectively.

Configure 'mod_jk' by running

./configure \
    --with-apxs=/usr/sbin/apxs \
    --with-tomcat41=$CATALINA_HOME \
    --with-java-home=$JAVA_HOME \
    --with-jni

make
make install

This will build mod_jk and install it as an Apache module

Configuration of Apache and mod_jk

Add the following lines to '/etc/http/conf/httpd.conf'. Check for paths to be correct.

#-------------------------------------------------------
#                      t o m c a t
#-------------------------------------------------------

# Load mod_jk module
LoadModule jk_module modules/mod_jk.so

# Where to find workers.properties
JkWorkersFile /etc/httpd/conf/workers.properties

# Where to put jk logs
JkLogFile /var/log/httpd/mod_jk.log
JkLogLevel info
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 "%w %V %T"

# Send everything for context /examples to worker named worker1 (ajp13)
# JkMount /examples/* worker1
# JkMount /* worker1

We comment out JkMount lines because we will define them at the virtual host level.

Configure workers by creating the file '/etc/httpd/conf/workers.properties':

# Define 1 real worker using ajp13
 worker.list=worker1

# Set properties for worker1 (ajp13)
 worker.worker1.type=ajp13
 worker.worker1.host=localhost
 worker.worker1.port=8009
 worker.worker1.lbfactor=50
 worker.worker1.cachesize=10
 worker.worker1.cache_timeout=600
 worker.worker1.socket_keepalive=1
 worker.worker1.socket_timeout=300

Each worker is a Tomcat instance; you can define more than one if you run multiple webapps each in their own Virtual Machine, for maximum security.

Virtual host configuration

You basically have two possible approaches to mounting webapps in Apache so that their content s handled by Tomcat:

  • Redirecting: you tell Tomcat that some URLs (e.g. the ones ending in .jsp) are to be handled by Tomcat, while all other files are server statically by Apache itself. This requires the webapp to be present on the same host as Tomcat

  • Proxying: you tell Apache to forward all requests within a specified virtual host to Tomcat for serving. The server may be on a different host, therefore making it possible to server contents from an external server.

You can use either model but - of course - you cannot use both for the same QueueMetrics instance.

Model 1: Redirecting some URLs to JK

Check the following lines in 'httpd.conf':

Listen 80
NameVirtualHost *

Add the following lines for each Virtual Host you want to support:

<VirtualHost *>
    ServerName queuemetrics.example.com
    ServerAlias queuemetrics_test.example.com
    ServerAdmin webmaster@example.com

    DocumentRoot /var/www/virtualhost/example.com/queuemetrics
    CustomLog /var/log/httpd/queuemetrics.example.com_access.log common
    ErrorLog /var/log/httpd/queuemetrics.example.com_error.log
    AddDefaultCharset UTF-8

    JkMount /*.jsp worker1
    JkMount /*.do worker1
    JkMount /tpf worker1
    JkMount /manager/* worker1
</VirtualHost>

You can include or exclude the '/manager' path in order to access Tomcat’s manager.

Model 2: Using Apache as a proxy to Tomcat

Using this model, you forward requests to a Tomcat server that may or may not be on the same host. All requests for this domain are forwarded.

 <VirtualHost *:80>
    ServerName queuemetrics.example.com
    ServerAlias queuemetrics_test.example.com

    CustomLog /var/log/httpd/queuemetrics.example.com_access.log common
    ErrorLog /var/log/httpd/queuemetrics.example.com_error.log

    AddDefaultCharset UTF-8

    ProxyPreserveHost On
    ProxyPass / ajp://localhost:8009/
    ProxyPassReverse / ajp://localhost:8009/
</VirtualHost>

As the AJP request contains the full virtual host information, you still have to set up a virtual host in Tomcat for the hosts you need to proxy.

Of course, you could have Tomcat reside on a separate server on the same subnet, so you would offload all computation-intensive activities from your internet-facing server to a separate server that runs QueueMetrics.

Creating Virtualhosts in Tomcat

Turning off unnecessary connectors

Within Tomcat’s 'server.xml' file, within the section marked by 'SERVICE NAME="Catalina"', remove all connector entries but the one here:

<!-- Define a Coyote/JK2 AJP 1.3 Connector on port 8009 -->
    <Connector port="8009"
               enableLookups="false" redirectPort="8443" debug="0"
               protocol="AJP/1.3" />

This is the access point for Apache. This port should be unreachable outside this box.

Enabling the virtual host

By the end of 'server.xml', after the default virtual host (section '<Host>…​</Host>') add an entry like:

<Host name="queuemetrics.example.com"  debug="0"
	appBase="/var/www/virtualhost/example.com/queuemetrics"
	unpackWARs="true">
	<Alias>qm2.example.com</Alias>

	<Logger className="org.apache.catalina.logger.FileLogger"
		directory="/var/log/httpd"
		prefix="queuemetrics.example.com_tomcat-" suffix=".log"
           timestamp="false"/>

	<Context path="" docBase="" debug="0" reloadable="true"/>

   <Context path="/manager" debug="0" privileged="true"
       docBase="/usr/local/queuemetrics/tomcat/webapps/manager">
   </Context>
</Host>

If you want the manager webapp to be available, you need to include the context path as in the example above (check the path to be correct).

Restart everything.

/etc/init.d/httpd restart
/etc/init.d/queuemetrics restart

Check the logs when restarting. Go to http://queuemetrics.example.com/queuemetrics and check that QueueMetrics is working.

Troubleshooting

If you see lines like these appear on 'catalina.out':

org.apache.jk.common.HandlerRequest decodeRequest
WARNING: Error registering request

You need to locate the file 'jk2.properties' and add/edit the following line:

request.registerRequests=false

CAUTION: This change must be made when Tomcat is stopped, or it will overwrite it when it terminates.