I have set up an Apache Tomcat Cluster with an Apache HTTP server and load balancing on CentOS 6.6 the following way:

+ 1 VM running HTTP server & 1 Tomcat instance (used for deployment, not answering requests)
+ 1 VM running 2 Tomcat instances on different ports

Important things first:
+ watchEnabled: on master = "true", on slaves = "false"
+ HTTP connector only for master node, not defined on slaves
+ port for AJP connector different on every instance
+ tcpListenerPort for NioReceiver different on every instance
+ jvmRoute value equals respective hostname on all instances
+ path to watchDir / tempDir different, deployDir = webapps on every instance
+ port for shutdown different on every instance
+ firewalld/iptables turned off on all nodes (testing environment)
+ YES, I have read lots of things about this topic (official documentation, tutorials, etc...) already.

server.xml (only the important part)

<Server port="8004" shutdown="SHUTDOWN">
  <Service name="Catalina">
    <!-- HTTP connector on port 8081 -->
      port="8081" protocol="HTTP/1.1" 
    <!-- Define an AJP 1.3 Connector on port 8012 -->
    <!-- Engine definition for clustering -->
      <Realm className="org.apache.catalina.realm.MemoryRealm"/>
          <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
          <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/>
          <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
          <Channel className="org.apache.catalina.tribes.group.GroupChannel">
            <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">


<VirtualHost *:80>
  DocumentRoot /var/www/html

  ProxyRequests Off
  ProxyPreserveHost On

  <Proxy *>
    Order deny,allow
    Allow from all

  <Proxy balancer://testcluster>
    BalancerMember ajp:// route=acd11-node01
    BalancerMember ajp:// route=acd11-node02
    ProxySet lbmethod=byrequests

  # Exclude balancer-manager app to make it available on master
  ProxyPass /balancer-manager !

  ProxyPass / balancer://testcluster/ stickysession=JSESSIONID|jsessionid
  ProxyPassReverse / balancer://testcluster/ stickysession=JSESSIONID|jsessionid

  <Location /balancer-manager>
    SetHandler balancer-manager


Apache error log (what it gives me after startup):

[Tue Jan 06 08:29:49.235859 2015] [mpm_prefork:notice] [pid 9655] AH00170: caught SIGWINCH, shutting down gracefully
[Tue Jan 06 08:29:50.306520 2015] [core:notice] [pid 9727] SELinux policy enabled; httpd running as context system_u:system_r:httpd_t:s0
[Tue Jan 06 08:29:50.307867 2015] [suexec:notice] [pid 9727] AH01232: suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Tue Jan 06 08:29:50.319218 2015] [so:warn] [pid 9727] AH01574: module proxy_module is already loaded, skipping
[Tue Jan 06 08:29:50.319797 2015] [so:warn] [pid 9727] AH01574: module proxy_ajp_module is already loaded, skipping
[Tue Jan 06 08:29:50.319827 2015] [so:warn] [pid 9727] AH01574: module proxy_balancer_module is already loaded, skipping
[Tue Jan 06 08:29:50.320610 2015] [so:warn] [pid 9727] AH01574: module proxy_http_module is already loaded, skipping
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::50a0:e2ff:fe74:5294. Set the 'ServerName' directive globally to suppress this message
[Tue Jan 06 08:29:50.328101 2015] [auth_digest:notice] [pid 9727] AH01757: generating secret for digest authentication ...
[Tue Jan 06 08:29:50.329387 2015] [lbmethod_heartbeat:notice] [pid 9727] AH02282: No slotmem from mod_heartmonitor
[Tue Jan 06 08:29:50.333216 2015] [mpm_prefork:notice] [pid 9727] AH00163: Apache/2.4.6 (CentOS) configured -- resuming normal operations
[Tue Jan 06 08:29:50.333263 2015] [core:notice] [pid 9727] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'

What I try to achieve:
We have many enterprise web applications which we wanna load balance throughout a Tomcat farm.

What does work:
+ Tomcat clustering
+ Replication
+ FarmWarDeployer

What doesn't work:
Whenever I try to call an application that's been deployed throughout the cluster, it gives me 404 not found. Same for Tomcat root applications such as /manager/html or /host-manager. Only application that is working is /balancer-manager, obviously.

The httpd server is supposed to serve as a load balancer and proxy to the tomcats. It will have to deliver some static content but first and foremost, I need to get this thing up and running to load balance the JavaEE applications (servlets). AJP to the cluster nodes is a must have for me, since http access must not be allow (+ for some other reasons that are worth a totally different discussion).

Since everybody seems to set up the mod_proxy configuration in a different manner, I am looking for a straight forward solution that gives me something I can build on. If you need more information or more configuration details, let me know and I will provide you with those. I already have a second cluster configured using mod_jk and everything is working as intended, but the Stakeholders require this mod_proxy(_ajp) thing and it just grinds my gears.

Your help is much appreciated!

Best regards!

  • Is the 404 from Tomcat or Apache?
    – ETL
    Jan 6, 2015 at 2:43
  • From Apache, it's shown in the HTTP request. Jan 6, 2015 at 5:32
  • What is in your Apache error log?
    – ETL
    Jan 6, 2015 at 16:18
  • Also, just to be sure - the web app does not redirect to https right? As that could give you a problem with the config above.
    – ETL
    Jan 6, 2015 at 16:19
  • In your config above, your AJP connector is using port 8012. Your apache config points to 8011 and 8010. Another typo?
    – ETL
    Jan 6, 2015 at 16:21

1 Answer 1


I haven't tried reproducing your configuration but when I looked at it this morning, it looks like the problem is simply a missing space and possibly the ProxyPassReverse not matching the ProxyPass (however the later wouldn't give you a 404 I think).

ProxyPass / balancer://testcluster/stickysession=JSESSIONID|jsessionid

ProxyPassReverse / balancer://testcluster/

should be:

ProxyPass / balancer://testcluster/ stickysession=JSESSIONID|jsessionid

ProxyPassReverse / balancer://testcluster/ stickysession=JSESSIONID|jsessionid

At least, that's how I have mine and I have no issue (but I don't use AJP, just regular http proxy).

Obviously this is assuming all the basic stuff are in place (site enabled, reload, http proxy mod installed and enabled, etc).

  • Thanks for your response. Unfortunately, this was just a typo in the post, original file looks good (regarding the missing space). Added stickysession=JSESSIONID|jsessionid to the PassProxyReverse, doesn't change anything. What I did find out tho is that if I call http://httpd_host:8081/manager/html, this gives me the manager app on the master node, but I don't want to type in the port number everytime. Still, if I call http://httpd_host:8081/app_context/app_url_pattern it gives me the app on the master node, but this node should not answer requests at all, and w/o a port it doesn't work Jan 6, 2015 at 16:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .