Implementation of multiple instances of tomcat on a single machine

Implementation of multiple instances of tomcat on a single machine

1. Introduction

First of all, we need to answer a question: why use multiple instances on a single machine?
In the absence of downtime, there are multiple projects in webapps. One of the projects may cause tomcat to crash due to excessive memory usage or other uncertain factors, then the projects under the same tomcat will also crash. However, when using different tomcats, each tomcat process is different on the same server. If a project has a problem and tomcat crashes, other projects will not be affected because they are in different processes.
Another question is that different tomcats use different ports, and there is only one domain name. How to allocate it?
In fact, this uses nginx's reverse proxy. According to the prefix of the request, it can proxy to the nginx server corresponding to the corresponding tomcat project service port.

2. System environment

System: 16.04.5 LTS
JDK version: openjdk 1.8
tomcat version: apache-tomcat-9.0.13

3. Environment Construction

3.1、Download Tomcat

Install jdk:

apt-get install openjdk-8-jdk

Visit the official website: https://tomcat.apache.org/download-90.cgi


Find core, click tar.gz and copy the download address when a download link pops up.
Then download tomcat using the command

wget http://mirrors.hust.edu.cn/apache/tomcat/tomcat-9/v9.0.13/bin/apache-tomcat-9.0.13.tar.gz

Unzip tomcat:

tar -xzvf apache-tomcat-9.0.13.tar.gz

Create a program directory:

##Create a program directory mkdir /data

##Move the unzipped file to the data directory mv ./apache-tomcat-9.0.13 /data/

cp /etc/profile /etc/profile.bak
echo "export CATALINA_HOME=/data/apache-tomcat-9.0.13" >> /etc/profile
echo "export PATH=\$PATH:\$CATALINA_HOME/bin">> /etc/profile && source /etc/profile
##Create sh file touch tomcat-start.sh tomcat-stop.sh

##Change permissions chmod 760 /data/tomcat-start.sh /data/tomcat-stop.sh

Back up the profile, write tomcat's CATALINA_HOME to the environment variable, and activate the environment variable.

create tomcat-start.sh, the content is as follows:

#!/bin/bash
##CATALINA_BASE here is the parent directory of the current script. If it is not in the subdirectory of CATALINA_BASE, remember to modify export CATALINA_BASE=$(cd $(dirname $0); cd .. ; pwd)

echo $CATALINA_BASE

TOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2}'`

if [ -n "$TOMCAT_ID" ] ; then
echo "tomcat($TOMCAT_ID) still running now, please shutdown it first";
 exit 2;
fi

TOMCAT_START_LOG=`$CATALINA_HOME/bin/startup.sh`

if [ "$?" = "0" ]; then
	echo "shell script: $0"
 echo "CATALINA_BASE: $CATALINA_BASE"
 echo "tomcat thread: $TOMCAT_ID"
 echo "start succeed!!!"
else
 echo "$0 $CATALINA_BASE start failed"
 echo $TOMCAT_START_LOG
fi

create tomcat-stop.sh, the content is as follows:

#!/bin/bash
##CATALINA_BASE here is the parent directory of the current script. If it is not in the subdirectory of CATALINA_BASE, remember to modify export CATALINA_BASE=$(cd $(dirname $0); cd .. ; pwd)

echo $CATALINA_BASE

TOMCAT_ID=`ps aux |grep "java"|grep "[D]catalina.base=$CATALINA_BASE "|awk '{ print $2}'`

if [ -n "$TOMCAT_ID" ] ; then
TOMCAT_STOP_LOG=`$CATALINA_HOME/bin/shutdown.sh`
else
 echo "Tomcat instance not found : $CATALINA_BASE"
 exit
fi

if [ "$?" = "0" ]; then
 echo "shell script: $0"
 echo "CATALINA_BASE: $CATALINA_BASE"
 echo "stop succeed!!!"
else
 echo "$0 $CATALINA_BASE stop failed"
 echo $TOMCAT_STOP_LOG
fi

Copy two tomcats:

##Complete deleting the contents of the lib and bin folders and generating an empty bin folder cp -r apache-tomcat-9.0.13 /data/apache-tomcat-test1 && cd /data/apache-tomcat-test1 && rm -rf lib/ bin/ && mkdir bin && cd -

##Copy the start and stop scripts to the bin folder, copy with permissions cp -p tomcat-start.sh tomcat-stop.sh /data/apache-tomcat-test1/bin/

##Copy the same tomcat directory with permissions cp -Rp /data/apache-tomcat-test1/ /data/apache-tomcat-test2/

Configure server.xml port

As you know, different Tomcats deployed on the same server must set different ports, otherwise there will be port conflicts, so we only need to modify the first three ports in conf/server.xml. But there are four of them:

  • Server Port: This port is used to listen for the shutdown command to shut down Tomcat. The default value is 8005.
  • Connector HTTP Port: This port is used to listen for HTTP requests. The default value is 8080.
  • Connector AJP Port: This port is used to listen for requests on the AJP (Apache JServ Protocol) protocol. It is usually used to integrate other HTTP servers such as Apache Server. The default port is 8009.
  • Redirect Port: Redirect port, appears in the Connector configuration. If the Connector only supports non-SSL ordinary http requests, then the port will forward https requests to the port specified by the Redirect Port. The default is 8443.

Uncommented version:

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
 <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
 <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
 <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
 <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
 <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
 <GlobalNamingResources>
 <Resource name="UserDatabase" auth="Container"
    type="org.apache.catalina.UserDatabase"
    description="User database that can be updated and saved"
    factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
    pathname="conf/tomcat-users.xml" />
 </GlobalNamingResources>
 <Service name="Catalina">
 <Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />
 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
 <Engine name="Catalina" defaultHost="localhost">
  <Realm className="org.apache.catalina.realm.LockOutRealm">
  <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
    resourceName="UserDatabase"/>
  </Realm>
  <Host name="localhost" appBase="webapps"
   unpackWARs="true" autoDeploy="true">
  <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    prefix="localhost_access_log" suffix=".txt"
    pattern="%h %l %u %t &quot;%r&quot; %s %b" />
  </Host>
 </Engine>
 </Service>
</Server>

tomcat-test1 is changed to:

  • Server Port: 9015
  • Connector HTTP Port: 9010
  • Connector AJP Port: 9019

tomcat-test2 is changed to:

  • Server Port: 9025
  • Connector HTTP Port: 9020
  • Connector AJP Port: 9029

Modify the logo:

echo "test1"> /data/apache-tomcat-test1/webapps/ROOT/index.jsp
echo "test2"> /data/apache-tomcat-test2/webapps/ROOT/index.jsp

After the modification is completed, start tomcat:

/data/apache-tomcat-test1/bin/tomcat-start.sh
/data/apache-tomcat-test2/bin/tomcat-start.sh


The curl process is relatively slow because it has not yet completed. After starting it up it's fine.

curl 127.0.0.1:9010
curl 127.0.0.1:9020

Note that the access port here is the port corresponding to Connector HTTP Port

4. Postscript

In fact, it is not difficult to set up. According to the idea of ​​the reference article, it is to share a tomcat lib and bin. In this way, you only need to replace the lib when upgrading, and the bin uses the same script of CATALINA_HOME. In fact, the start and shutdown scripts under the bin under CATALINA_HOME uniformly call catalina.sh, and the single-machine multi-instance system巧妙運用了catalina.sh是通過環境中的CATALINA_HOME和CATALINA_BASE變量啟動tomcat的. By改變CATALINA_BASE的路徑達到同一條腳本啟動tomcat在不同目錄下.

5. Question

5.1. Tomcat starts slowly

It can be seen that because it takes 1 minute and 6 seconds to generate the session ID, which is too long, the overall time of application deployment is greatly increased. This problem can be solved by adding the jvm parameter -Djava.security.egd=file:/dev/./urandom when starting the application. However, this will weaken the application's ability to generate random numbers, or the randomness is not uniform enough, which may have security implications for applications that often use encryption.
Modify the startup script and add the JAVA_OPTS setting. JAVA_OPTS can be used because catalina.sh will read this variable.

#!/bin/bash
##CATALINA_BASE here is the parent directory of the current script. If it is not in the subdirectory of CATALINA_BASE, remember to modify export CATALINA_BASE=$(cd $(dirname $0); cd .. ; pwd)
echo $CATALINA_BASE

TOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2}'`

export JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom";

if [ -n "$TOMCAT_ID" ] ; then
echo "tomcat($TOMCAT_ID) still running now, please shutdown it first";
 exit 2;
fi

TOMCAT_START_LOG=`$CATALINA_HOME/bin/startup.sh`

if [ "$?" = "0" ]; then
  echo "shell script: $0"
 echo "CATALINA_BASE: $CATALINA_BASE"
 echo "tomcat thread: $TOMCAT_ID"
 echo "start succeed!!!"
else
 echo "$0 $CATALINA_BASE start failed"
 echo $TOMCAT_START_LOG
fi

5.2. When using remote ssh, the environment variables do not take effect

Use the source command to refresh the current environment variables.

The specific modifications are as follows:

tomcat-start.sh :

#!/bin/bash
##CATALINA_BASE here is the parent directory of the current script. If it is not in the subdirectory of CATALINA_BASE, remember to modify the source /etc/profile
export CATALINA_BASE=$(cd $(dirname $0); cd .. ; pwd)
export JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom";
TOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2}'`

echo "----------------------------------"
echo "Using CATALINA_BASE:$CATALINA_BASE"
echo "Using CATALINA_HOME:$CATALINA_HOME"
echo "----------------------------------"

if [ -n "$TOMCAT_ID" ] ; then
echo "tomcat($TOMCAT_ID) still running now, please shutdown it first";
 exit 2;
fi

TOMCAT_START_LOG=`$CATALINA_HOME/bin/startup.sh`

if [ "$?" = "0" ]; then
	echo "shell script: $0"
 echo "tomcat thread: $TOMCAT_ID"
 echo "start succeed!!!"
else
 echo "$0 $CATALINA_BASE start failed"
	echo "CATALINA_BASE: $CATALINA_BASE"
 echo $TOMCAT_START_LOG
fi

tomcat-stop.sh

#!/bin/bash
## CATALINA_BASE here is the parent directory of the current script. If it is not in the subdirectory of CATALINA_BASE, remember to modify the source /etc/profile
export CATALINA_BASE=$(cd $(dirname $0); cd .. ; pwd)
TOMCAT_ID=`ps aux |grep "java"|grep "[D]catalina.base=$CATALINA_BASE "|awk '{ print $2}'`

echo "----------------------------------"
echo "Using CATALINA_BASE:$CATALINA_BASE"
echo "Using CATALINA_HOME:$CATALINA_HOME"
echo "----------------------------------"

if [ -n "$TOMCAT_ID" ] ; then
TOMCAT_STOP_LOG=`$CATALINA_HOME/bin/shutdown.sh`
else
 echo "Tomcat instance not found : $CATALINA_BASE"
 exit
fi

if [ "$?" = "0" ]; then
 echo "shell script: $0"
 echo "stop succeed!!!"
else
 echo "$0 $CATALINA_BASE stop failed"
	echo "CATALINA_BASE: $CATALINA_BASE"
 echo $TOMCAT_STOP_LOG
fi

Attach the restart script:
tomcat-restart.sh :

#!/bin/bash

source /etc/profile
export CATALINA_BASE=$(cd $(dirname $0); cd .. ; pwd)
GREEN_COLOR='\E[1;32m' # Green RES='\E[0m'

TOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2}'`

SLEEP_TIME=1

echo "----------------------------------"
echo "Using CATALINA_BASE:$CATALINA_BASE"
echo "Using CATALINA_HOME:$CATALINA_HOME"
echo "----------------------------------"

if [ -n "$TOMCAT_ID" ] ; then
 echo -e "${GREEN_COLOR}found tomcat instance in pid $TOMCAT_ID , shutdown now!${RES}";
 echo -e "${GREEN_COLOR}---------------start shutdown-------------------${RES}"
 source $(dirname $0)/tomcat-stop.sh;
 echo -e "${GREEN_COLOR}--------------- end shutdown -------------------${RES}"
fi

while [ -n "$TOMCAT_ID" ]
do 
 sleep $SLEEP_TIME
 echo wait "$SLEEP_TIME" s
 TOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2}'`
done 

echo -e "${GREEN_COLOR}---------------start startup-------------------${RES}"
source $(dirname $0)/tomcat-start.sh
echo -e "${GREEN_COLOR}---------------end startup-------------------${RES}"

Reference blog:

Let's talk about Tomcat's single machine multiple instances

Spring Boot application slow startup for the first time

This is the end of this article about the implementation of multiple instances of tomcat on a single machine. For more relevant content about multiple instances of tomcat on a single machine, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed explanation of shell script for deploying multiple instances of a single tomcat in Linux
  • Detailed explanation of the process of deploying Tomcat and creating the first web project in IDEA 2020.3.1
  • Where is the project location deployed by IntelliJ IDEA using Tomcat?
  • Tomcat multi-instance deployment and configuration principles

<<:  js to achieve image fade-in and fade-out effect

>>:  Why MySQL should avoid large transactions and how to solve them

Recommend

Docker Data Storage Volumes Detailed Explanation

By default, the reading and writing of container ...

Problems and experiences encountered in web development

<br />The following are the problems I encou...

Vue's global watermark implementation example

Table of contents 1. Create a watermark Js file 2...

Detailed explanation of Docker data backup and recovery process

The data backup operation is very easy. Execute t...

The scroll bar position is retained when scrolling the vant list component

The scroll bar position is retained when scrollin...

Detailed example of creating and deleting tables in MySQL

The table creation command requires: The name of...

Practical record of Vue3 combined with TypeScript project development

Table of contents Overview 1. Compositon API 1. W...

Vue encapsulation component tool $attrs, $listeners usage

Table of contents Preface $attrs example: $listen...

Let's talk about the storage engine in MySQL

Basics In a relational database, each data table ...

HTML page jump and parameter transfer issues

HTML page jump: window.open(url, "", &q...

vue+el-upload realizes dynamic upload of multiple files

vue+el-upload multiple files dynamic upload, for ...

Share 9 Linux Shell Scripting Tips for Practice and Interviews

Precautions 1) Add interpreter at the beginning: ...

Analysis of MySQL lock mechanism and usage

This article uses examples to illustrate the MySQ...

Detailed explanation of several ways to create objects and object methods in js

This article is the second article about objects ...