Configuring Apache in front of JBoss Application Server Using mod_jk
Introduction
Apache HTTP server is a highly reliable and proven open source/free web server. It is under development for over 15 years and is used extensively to host web sites. Since Apache is very popular and the source code is available, security experts are always looking for any vulnerability. This makes it one of the most secure web servers.
JBoss AS is a popular open source J2EE application server widely used for deploying web applications. JBoss is powered by Tomcat servlet container which can also work as a Web server. However in many production deployments, Apache is configured as the web server in front of the JBoss server. This is due to the extensive set of features/deployment options offered by Apache HTTP server.
This article provides a step by step guide on configuring Apache HTTP server as the Web server in front of the JBoss application server. This guide is written for Microsoft Windows systems (Windows XP, Windows 7, Windows Server 2008 etc.). However the steps mentioned are similar on a Linux based system.
The following diagram depicts a typical production setup of a high availability Web application built on J2EE technologies.
A hardware load balancer in front ensures highly reliable load balancing. Apache web servers configured behind a hardware load balancer ensures availability of the web application even when one of the servers are taken down for maintenance. Apache servers balances the load among the Jboss applications servers via the mod_jk connector. The Jboss servers are configured in a cluster and hence when a server goes down, the subsequent user requests can be forwarded to a different server.
Why to Configure Apache HTTP server in front of JBoss Application Server?
Application servers are good at hosting Web applications, but they are not as good when it comes to serving static content, providing load balancing, URL rewriting, security etc. Following are some of the advantages of using Apache HTTP web server in front of an application server such as JBoss.
- Apache is a high performance and highly secure Web server with advanced features. It is a proven server and as of 2010, it is run on over 100 million servers.
- Apache comes with a lot of extension modules providing essential hosting features such as logging, virtual hosting, URL rewriting etc.
- Apache can be used as a load balancer distributing load across multiple JBoss instances. Mod_jk connector supports advanced load balancing configurations.
- A single Apache server instance can serve multiple domains using virtual hosting and at the same time they can all be serviced by different JBoss servers. This ensures process isolation for web applications hosted in each domain.
Installing JBoss Application Server
Download JBoss Application Server from here. For this example, I have downloaded JBoss 6.0.
After downloading the file, extract the zip file to a folder of your choice. From the Windows command line, change to the bin directory inside the JBoss installation and run the following command. This will start JBoss on the default HTTP port of 8080. The –b option is used to bind JBoss to all network interfaces.
Verify that JBoss sever is up and running by accessing the default console application at the URL – http://localhost:8080/. Create a sample application and host it under the App1 context. Verify that your application is running by accessing the URL – http://localhost:8080/App1.
Installing Apache HTTP Server
Download Apache HTTP server 2.x version from here. For Windows, best option is to download the MSI installer. Double click on the MSI file to install Apache. By default Apache is installed on port 80 and it is configured as a Windows service. If you have trouble running Apache, check whether there are any other applications listening on port 80 (Skype is a usual culprit).
Apache to JBoss Request Routing – How It Works?
There are two different ways of configuring Apache to JBoss routing. One is to use the Tomcat connector available for Apache called the mod_jk connector. This is an Apache module specifically written by Tomcat team. This module routes the Apache to JBoss request via the AJP (Apache Jserv Protocol).
Second method is to use an Apache module called mod_proxy. This proxy can either use HTTP or AJP for routing request from Apache to JBoss. The advantage of mod_proxy is that it is available as a built in module in Apache 2.x versions.
When it comes to load balancing and failure detection, mod_jk is better than mod_proxy. The only disadvantage is the need to separately deploy mod_jk module.
In either case, if the Apache connector is using AJP protocol, the AJP protocol listener must be enabled on the JBoss server. By default JBoss binds AJP service to the port 8009. Whenever a request is received by Apache, it looks at the AJP module configuration file(workers.properties) and if the request is intended for the JBoss server, the request is routed through AJP protocol to the port 8009(Please see the diagram above).
Configuring Apache to JBoss HTTP Request Routing Using Mod_Jk
To configure mod_jk integration, either download mod_jk source code or mod_jk binary for your platform from here. Copy the compiled or downloaded module to the modules directory of your Apache installation.
Now create a new file named mod-jk.conf inside apache/conf folder. Add the following content to this file. Please ensure that the name of the module (mod_jk-1.2.31-httpd-2.2.3.so) is changed to the actual module file copied to the modules directory.
LoadModule jk_module modules/mod_jk-1.2.31-httpd-2.2.3.so JkWorkersFile conf/workers.properties JkShmFile logs/mod_jk.shm JkLogFile logs/mod_jk.log JkLogLevel info JkMount /App1/* worker1 |
The directive JkMount here ensures that all HTTP requests with context /App1/ are forwarded to the worker1 application server configured in workers.properties (see below).
Open httpd.conf in apache/conf folder and add the following line at the end of the file. This enables the mod-jk.conf file as an extension to the default configuration file.
Include conf/mod-jk.conf |
Create a new file workers.properties inside apache/conf folder. Add the following content to the file. Note that the name of the JBoss node (worker1) corresponds to the JkMount configuration in mod-jk.conf file. The host in this case is given as localhost since I have the JBoss running on the same machine. In actual deployments replace localhost with the ip address/host name of the JBoss machine.
worker.list=worker1 worker.worker1.type=ajp13 worker.worker1.host=localhost worker.worker1.port=8009 |
The above configuration indicates that there is a single application server machine available for handling requests in the localhost and it is available through AJP protocol via port 8009.
Restart apache and JBoss and access your Web application through Apache server using this URL – http://localhost:80/App1.
Additional Reading
April 19, 2011 | Posted in Programming 5 Comments » | By Jayson
October 3rd, 2011 at 7:49 pm
hi
After i added “Include conf/mod-jk.conf” line to the httpd.conf i, then the apache server can not be restarted.It says “The request operation has failed”
October 19th, 2011 at 4:54 am
Same prob as told by dhanushka…
November 3rd, 2011 at 8:43 am
Hello,
I read through the passage, but as said above, the error is coming again and again.
Just please, explain a bit more about the line : JkMount /App1/* worker1.
Where exactly we talked about shifting stuff from Port 80 to Port 8080. Instead we brought a new port out of nowhere (Port 8009).
There is no such folder named App1 in either Tomcat or JBoss. Please do explain that line JkMount thing.
I be obliged.
Regards
March 8th, 2012 at 12:34 pm
it’s ok apache and jboss run correctly, but only one error no blocking on server.log will display no stop
java.lang.ArrayIndexOutOfBoundsException: 0
at org.apache.catalina.connector.CoyoteAdapter.normalize(CoyoteAdapter.java:647)
at org.apache.catalina.connector.CoyoteAdapter.postParseRequest(CoyoteAdapter.java:347)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:239)
at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:437)
at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:381)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:595)
why?
February 20th, 2015 at 4:49 pm
Hi
very nice post, everything works properly. The only change is:
worker.worker1.host=127.0.0.1
instead of:
worker.worker1.host=localhost
on my Centos6 + apache 2.2 + wildfly 8.1
Thanks