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.
    – Mosh Pit
    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
    – Mosh Pit
    Jan 6, 2015 at 16:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.