Home » DevOps » Multiple Tomcat Instances on Single Machine

About Ramki

Ramki is a Application Developer working in the C-DAC, Pune. He has Extensive Design and Development experience in Java, Java Server Faces, Servlets, Java Persistent API (Hibernate), CDI, EJB and experience in applying Design Patterns of JavaEE Architecture.

Multiple Tomcat Instances on Single Machine

In this post we will see how to run multiple tomcat instances on a single machine and under a single user account.

We first see the tomcat directory structure, where each folder has the following purpose:

bin –  contains all binary and script files for running tomcat.
lib – contains all shared libraries used for tomcat
conf – contains configuration information like which port tomcat can bind, etc.
logs – contains all log files
temp – this folder is used by Tomcat for temporary files
webapps – this folder is very important, we put here all the application war files
work – if an application contains JSPs, then each JSP is translated and converted into a servlet and is stored here
When we run Tomcat, it uses 5 environment variables. They are:
  • CATALINA_HOME
  • CATALINA_BASE
  • CATALINA_TMPDIR
  • JRE_HOME/JAVA_HOME
  • CLASSPATH
In the above list, CATALINA_HOME and JAVA_HOME are mandatory environment variables. All others are optional and can be calculated using CATALINA_HOME.
CATALINA_HOME – this environment variable should point to tomcat base folder, where tomcat binary are  installed/extracted. so based on CATALINA_HOME we can get bin and lib folder
CATALINA_BASE – If we not specified then CATALINA_HOME value is set. This variable pointed to configuration and webapps folder. Based on this variable server uses conf, logs, temp, webapps, work folders.

A usual way to run Tomcat is to only set the CATALINA_HOME environment variable and run the startup.sh script file. The startup.sh file automatically calculates and assigns the values of other variables which we have not set.

The startup.sh file sets the environment variable and  then calls catalina.sh. This file reads CATALINA_BASE value, attaches conf i.e $CATALINA_BASE/conf folder and gets server.xml. This file is the heart of Tomcat’s configuration. It contains all configuration information, like shutdown port, connector post, host name, application folder, etc. For example, Tomcat usually uses 8080 as a connector port, so we can access it at http://localhost:8080/.

If we set the $CATALINA_BASE explicitly, then Tomcat uses our variable to search and get the server.xml file from our target place, i.e what we specified in CATALINA_BASE. 
This trick can be used to run multiple Tomcat instances in a single machine. We don’t need to change the CATALINA_HOME value. We just need to change the CATALINA_BASE value before start/shutdown Tomcat.

Create one folder named “tomcat-instance1” and copy conf, logs, temp, webapps, work folder from CATALINA_HOME folder and change conf/server.xml file in tomcat-instance1. We need to change these ports: shutdown port, connector port, ajp port and redirect port.

Shutdown port – This port is used for shutting down Tomcat. When we call the shutdown.sh script, it sends a signal to shutdown port. This port is where the Tomcat Java process listens. If such signal is received, the process then cleans up and exits by itself.
Connector port -This port is the actual port that exposes the application to an outside client. 
ajp port – This port may be used by a web server (e.g. Apache httpd server) to communicate with Tomcat. This port is also used when we setup a load balanced server.
Redirect port – If the Connector is supporting non-SSL requests and a request is received for which a security constraint requires SSL, Catalina will automatically redirect the request to this port. 

Let’s see the sample server.xml file:

<server port="8005" shutdown="SHUTDOWN">
	.....
	<connector
		connectiontimeout="20000"port="8080"
		protocol="org.apache.coyote.http11.Http11NioProtocol"
		redirectport="8443" />
	<connector port="8009" protocol="AJP/1.3" redirectport="8443" />
</server>

So, we change these ports to different numbers, because once a port is binded, then an other process can’t bind it again. In tomcat-instance1/conf/server.xml file I configured server port =8105, connector port = 8181, ajp port = 8109.

<server port="8105" shutdown="SHUTDOWN">
	.....
	<connector
		connectiontimeout="20000" port="8181"
		protocol="org.apache.coyote.http11.Http11NioProtocol"
		redirectport="81443" />
	<connector port="8109" protocol="AJP/1.3" redirectport="81443" />
</server>

Now we can create two script files for starting up and shutting down the tomcat-instance1.

startup-instance1.sh

export CATALINA_BASE= /home/ramki/tomcat-instance1
cd $CATALINA_HOME/bin
./startup.sh

shutdown-instance1.sh

export CATALINA_BASE= /home/ramki/tomcat-instance1
cd $CATALINA_HOME/bin
./shutdown.sh

Here we explicitly set the CATALINA_BASE variable and point it to the new tomcat-instance1. Then we go to the CATALINA_HOME/bin folder because all binary files for running tomcat are still present there. Then we use the startup/shutdown cripts.

Based on the above technique, we can create many instance folders and change the conf/server.xml file port values and run that instance with their own newly created script files.

Reference: Running Multiple Tomcat Instances on Single Machine from our JCG partner Rama at the Ramkitech blog (original text was modified for readability reasons).

Related Articles :

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

and many more ....

 

12 comments

  1. One comment: also, if using java debugging port, you should change debugger port in different scripts.
    This did not work for me, until i set $JAVA_OPTS variable to use:
    -Xdebug -Xrunjdwp:transport=dt_socket,address=1045
    in other instance instead of
    -Xdebug -Xrunjdwp:transport=dt_socket,address=1044

    as debugging options.

  2. This is very useful. However there is no mention about where the two new script files (shutdown-instance1.sh and shutdown-instance1.sh) can go. Obviously there will not be any issue for the tomcat to start up. But if the applications are looking for files relative to working directory there could be problems. Application that works in the very first instance of tomcat, would fail in the second tomcat instance. So it is recommended to have the new script files in a folder named ‘bin’.

  3. One more thing. Please remember to remove all tomcat related applications (manager, docs, examples, default context etc) as required for your business. Some one in the team that sets up Tomcat instances for us, seems to blindly refer the steps in this blog and left out the default context :) With that the main domain points to the default tomcat page which has links to tomcat and oracle :)

  4. good trick to make multiple instance without multiple copies of tomcat

  5. Hi,
    i tried this and almoust everything works, although when i shutdown the server, it hangs in this line:

    INFO: Destroying ProtocolHandler [“http-bio-8183″] and if i start it this is what i get:

    INFO: Initializing ProtocolHandler [“http-bio-8183″]
    Mar 31, 2014 4:17:01 PM org.apache.coyote.AbstractProtocol init
    SEVERE: Failed to initialize end point associated with ProtocolHandler [“http-bio-8183″]
    java.net.BindException: Address already in use :8183
    at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:391)
    at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:554)
    at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:409)
    at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:119)
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:956)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:815)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:594)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:619)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:449)
    Caused by: java.net.BindException: Address already in use
    at java.net.PlainSocketImpl.socketBind(Native Method)
    at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
    at java.net.ServerSocket.bind(ServerSocket.java:376)
    at java.net.ServerSocket.(ServerSocket.java:237)
    at java.net.ServerSocket.(ServerSocket.java:181)
    at org.apache.tomcat.util.net.DefaultServerSocketFactory.createSocket(DefaultServerSocketFactory.java:49)
    at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:378)
    … 17 more

    Mar 31, 2014 4:17:01 PM org.apache.catalina.core.StandardService initInternal
    SEVERE: Failed to initialize connector [Connector[HTTP/1.1-8183]]
    org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-8183]]
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:106)
    at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:815)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:594)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:619)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:449)
    Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:958)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    … 12 more
    Caused by: java.net.BindException: Address already in use :8183
    at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:391)
    at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:554)
    at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:409)
    at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:119)
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:956)
    … 13 more
    Caused by: java.net.BindException: Address already in use
    at java.net.PlainSocketImpl.socketBind(Native Method)
    at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
    at java.net.ServerSocket.bind(ServerSocket.java:376)
    at java.net.ServerSocket.(ServerSocket.java:237)
    at java.net.ServerSocket.(ServerSocket.java:181)
    at org.apache.tomcat.util.net.DefaultServerSocketFactory.createSocket(DefaultServerSocketFactory.java:49)
    at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:378)
    … 17 more

    Mar 31, 2014 4:17:01 PM org.apache.catalina.startup.Catalina load
    INFO: Initialization processed in 791 ms
    Mar 31, 2014 4:17:01 PM org.apache.catalina.core.StandardService startInternal
    INFO: Starting service Catalina
    Mar 31, 2014 4:17:01 PM org.apache.catalina.core.StandardEngine startInternal
    INFO: Starting Servlet Engine: Apache Tomcat/7.0.26
    Mar 31, 2014 4:17:01 PM org.apache.catalina.startup.HostConfig deployWAR
    INFO: Deploying web application archive /home/remember/remembermeJM/webapps/RememberMeServer.war
    Mar 31, 2014 4:17:05 PM org.apache.catalina.startup.HostConfig deployWAR
    INFO: Deploying web application archive /home/remember/remembermeJM/webapps/axis2.war
    [INFO] Clustering has been disabled
    [INFO] Deploying module: metadataExchange-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/mex-1.6.2.mar
    [INFO] Deploying module: addressing-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/addressing-1.6.2.mar
    [INFO] Deploying module: jaxws-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/axis2-jaxws-mar-1.6.2.mar
    [INFO] Deploying module: mtompolicy-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/mtompolicy-1.6.2.mar
    [INFO] Deploying module: soapmonitor-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/soapmonitor-1.6.2.mar
    [INFO] Deploying module: ping-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/ping-1.6.2.mar
    [INFO] Deploying module: script-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/scripting-1.6.2.mar
    [INFO] Deploying Web service: PictureWS.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/PictureWS.aar
    [INFO] Deploying Web service: LocationWS.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/LocationWS.aar
    [INFO] Deploying Web service: RegistrationIdWS.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/RegistrationIdWS.aar
    [INFO] Deploying Web service: version-1.6.2.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/version-1.6.2.aar
    [INFO] Deploying Web service: AccelerometerWS.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/AccelerometerWS.aar
    [INFO] Deploying Web service: AmplitudeWS.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/AmplitudeWS.aar
    Mar 31, 2014 4:17:09 PM org.apache.catalina.startup.Catalina start
    INFO: Server startup in 7887 ms

    I have another instance running. But i have to have it running, because they are different applications. Can someone help me

    • the problem is ur using port 8183, but its already used by some process. check the netstat -tlpn command.

      change the port to different one. and make sure all are unique ports (unused).

      • But this also happens in one instance i have with port 8181 and before this instance was working properly is this some kind of problem where there is a proccess running in this ports that weren’t shutdown and still running?

  6. Hi,

    Although my question is not directly related to the subject matter above but it is related with tomcat server. My web-app generates Matlab figures using Matlab Java Builder in the tomcat server. These figures are created at run-time and gets destroyed on server re-start. I want to know where are the these temporary files located in the server so that I can delete them with another application.

    Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *

*


8 − = one

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Want to take your Java Skills to the next level?
Grab our programming books for FREE!
  • Save time by leveraging our field-tested solutions to common problems.
  • The books cover a wide range of topics, from JPA and JUnit, to JMeter and Android.
  • Each book comes as a standalone guide (with source code provided), so that you use it as reference.
Last Step ...

Where should we send the free eBooks?

Good Work!
To download the books, please verify your email address by following the instructions found on the email we just sent you.