Separate the Static from the Dynamic with Tomcat and Apache
Hosting multiple Java Web-enabled applications with Apache/SSL in combination with Tomcat is potentially highly detailed. Separating the dynamic from the static content requires URL rewriting and aliases. This article discusses one viable configuration.
I describe the basics of how to host multiple Java Web applications using a pure Apache project approach. In other words, I explain how to apply Apache, mod_ssl, some rewrite rules and the Tomcat Servlet container to gain control of a consistent and viable production environment. In real life, I am a more-than-a-little-busy developer, and one of my more-recent tasks was to define and implement a structure to host a complex database-intensive Web-enabled searchable publication mechanism through the life cycle. I condense the experience gained and explain the most relevant details here.
The basics of placing an Apache Web server in front of multiple Tomcat servers is explained in an article by Daniel McCarthy on the Linux Journal Web site (see Resources). I take this article somewhat further by adding the ability to provide secure communication via SSL and show how to optimize performance by separating dynamic content, such as JSP pages, from static content, such as HTML and images. Further security issues also are nodded at briefly.
The following preparations are for those who want to generate a working instance of the infrastructure mentioned. This infrastructure involves a locally configured Apache server running with two Tomcat instances, all being referenced from a Web browser via different loopback (127.0.0.x) addresses. This article is still worth reading without following through with the recipe.
I assume that the following have been installed: Apache 1.3x Web server, mod_ssl, mod_jk and two instances of a Tomcat 5.5.x server, one running the ajp1.3 connector on the standard port of 8009 and the shutdown port of 8005, and the other on port 8019 and 8015. I have chosen a plain-old stable and reliable Apache 1.3.x server over an Apache 2.x version on the principle that you shouldn't fix what isn't broken. At the Institutes for which I have been responsible, during the past few years they have run Apache 1.3.x without issue, the system administrators have built up their knowledge, and the systems are maintained and patched to the highest levels and snuggly sit in the maturity section of the Web server's life cycle. The same applies for the choice of mod_jk over mod_jk2. In fact, mod_jk2 development has been discontinued due to the complexity of configuration.
If you have a Debian-based Linux distribution, to install the Apache server without compiling, try the following:
sudo apt-get install apache sudo apt-get install libapache-mod-jk sudo apt-get install libapache-mod-ssl
You should now have a running Apache instance with the configuration files sitting under /etc/apache.
For the Tomcat servers, you have two choices. The first is to use one instance of the binary and then two instances of the configuration, and then run a startup script that applies the unique instance of the binary with different configurations. The second choice is to use two copies of the Tomcat server and modify the server.xml file. The advantage of the first approach is the avoidance of replication of executable code. However, this is nearly always a false economy. The second approach has advantages for complex environments where you want to host different versions of Tomcat servers. The second approach is more relevant for Application Service Providers that have multiple customers. A division exists between code that is written for Java 1.5 that runs natively in Tomcat 5.5 (without installing the 1.4 compatibility package) and Java 1.4 that runs in Tomcat 5. Furthermore, the Servlet implementation is more up to date the newer the Tomcat version. Due to the current velocity of change, software that is hosted for more than a year can be considered legacy, so there always will be a demand for the use of older but still reliable servers.
Next, we want to test only on the loopback addresses with no packets reaching the network. This can be achieved by modifying the /etc/hosts file to something similar to:
127.0.0.10 bronze_a 127.0.0.11 silver 127.0.0.12 gold
Therefore, every time you type https://bronze_a, no DNS lookups are necessary. The packets from the browser never will reach the Internet and will stay local to 127.0.0.10.
In the main Apache configuration file, httpd.conf, you will find an include line that tells Apache to look under the conf.d directory for further configuration. For example:
Every time a package is installed that requires configuration changes for Apache, you will find an extra configuration file within the conf.d directory. In fact, if you want (for a nice aside), try to install Drupal and read the Drupal.conf file that is dumped.
I want to keep our work separate from the rest of the world's. No doubt, we will generate mistakes during playtime. Add a second line to include a directory for our virtual hosting files:
Then, make the directories /etc/apache/ssl and /etc/apache/vhosts. Later, we will place our certificates and server keys in the SSL directory, one set per virtual host.
Next, check the httpd.conf file to see whether the SSL engine is turned on. I want to turn the engine off until enabled per virtual host. So, the line SSLEngine On should change to SSLEngine Off.
Now we have an Apache 1.3.x server that is ready for action.
If you have not set up your Tomcat servers yet, you need to modify the following lines under the tomcat_root/conf/server.xml file for the second instance. Change the port numbers to 8015 for the shutdown command and port 8019 for the AJP/1.3 connector:
<Server port="8005" shutdown="SHUTDOWN"> <Connector port="8080" <Connector port="8009" enableLookups="false" protocol="AJP/1.3" />
For the sake of security, change the shutdown attribute from the value SHUTDOWN to some randomly long string. Otherwise, perhaps on the worst day under a badly defended system, a cracker can Telnet in and type SHUTDOWN, and then your server is down. Also, I would comment out the 8080 connector. There is no need to expose Tomcat directly to the Internet.
Only one task is left—to create two Web applications. Under the webapps directory of the first Tomcat instance, create a bronze_a directory, and then under that directory, create a WEB-INF directory. Place the following web.xml file in WEB_INF:
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>BRONZE_A</display-name> <description> BRONZE_A Dynamic </description> <welcome-file-list> <welcome-file> index.jsp </welcome-file> </welcome-file-list> </web-app>
Notice the mention of web-app_2_4.xsd. This web.xml file will not work under Tomcat 5, which uses the 2.3 standard. Under the webapps/bronze_a directory, place the following index.jsp file. This is our poor yet relevant example of dynamic content:
<%String mess="Hello World from Bronze_a"; %> <%=mess%> <br><%=request.getRequestURI()%>
Follow the same procedure for the second instance, but replace the string bronze_a with silver under the webapps/silver directory of the second Tomcat instance.
- Is the Private Cloud a Real Cloud?
- Give new life to old phones and tablets with these tips!
- Readers' Choice Awards 2014 Poll
- Linux Systems Administrator
- Senior Perl Developer
- Technical Support Rep
- Tech Tip: Really Simple HTTP Server with Python
- Memory Ordering in Modern Microprocessors, Part I
- Returning Values from Bash Functions