1、前言 首先要回答一个问题,为什么要用单机多实例? 在不宕机的情况下,webapps里面存在多个项目,可能由于其中一个项目过度使用内存或者其他不确定的因素使得tomcat挂了,那么同一tomcat下的项目也会一同挂了;而使用不同的tomcat,同一台服务器下,每个tomcat的进程是不一样的额,一个项目出现问题tomcat挂了,那么由于是在不同进程,其他项目不会影响的。 还有一个问题就是不同tomcat使用了不同端口,最后域名只有一个怎么分配? 其实这个使用nginx的反向代理,根据请求的前缀,代理到相应的tomcat项目服务端口对应的nginx server即可。 2、系统环境 系统:16.04.5 LTS JDK版本:openjdk 1.8 tomcat版本:apache-tomcat-9.0.13 3、环境搭建 3.1、下载tomcat 安装jdk: apt-get install openjdk-8-jdk 访问官网:https://tomcat.apache.org/download-90.cgi

找到core,点击tar.gz带弹出下载连接复制下载地址。 然后使用命令下载tomcat wget http://mirrors.hust.edu.cn/apache/tomcat/tomcat-9/v9.0.13/bin/apache-tomcat-9.0.13.tar.gz 解压tomcat: tar -xzvf apache-tomcat-9.0.13.tar.gz 建一个程序目录: ##创建一个程序目录mkdir /data##移动解压文件到data目录下mv ./apache-tomcat-9.0.13 /data/cp /etc/profile /etc/profile.bakecho "export CATALINA_HOME=/data/apache-tomcat-9.0.13" >> /etc/profileecho "export PATH=/$PATH:/$CATALINA_HOME/bin">> /etc/profile && source /etc/profile##创建sh文件touch tomcat-start.sh tomcat-stop.sh##更改权限chmod 760 /data/tomcat-start.sh /data/tomcat-stop.sh 备份profile,并写入tomcat的CATALINA_HOME到环境变量,激活环境变量。 创建 tomcat-start.sh,内容如下: #!/bin/bash##这里的CATALINA_BASE,是当前脚本的的父目录,如果不在CATALINA_BASE的子目录的话,记得修改export CATALINA_BASE=$(cd $(dirname $0); cd .. ; pwd)echo $CATALINA_BASETOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2}'`if [ -n "$TOMCAT_ID" ] ; thenecho "tomcat($TOMCAT_ID) still running now , please shutdown it first"; exit 2;fiTOMCAT_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_LOGfi 创建 tomcat-stop.sh,内容如下: #!/bin/bash##这里的CATALINA_BASE,是当前脚本的的父目录,如果不在CATALINA_BASE的子目录的话,记得修改export CATALINA_BASE=$(cd $(dirname $0); cd .. ; pwd)echo $CATALINA_BASETOMCAT_ID=`ps aux |grep "java"|grep "[D]catalina.base=$CATALINA_BASE "|awk '{ print $2}'`if [ -n "$TOMCAT_ID" ] ; thenTOMCAT_STOP_LOG=`$CATALINA_HOME/bin/shutdown.sh`else echo "Tomcat instance not found : $CATALINA_BASE" exitfiif [ "$?" = "0" ]; then echo "shell script: $0" echo "CATALINA_BASE: $CATALINA_BASE" echo "stop succeed!!!"else echo "$0 $CATALINA_BASE stop failed" echo $TOMCAT_STOP_LOGfi 复制两个tomcat: ##完成删除lib和bin文件夹内容,生成空的bin文件夹cp -r apache-tomcat-9.0.13 /data/apache-tomcat-test1 && cd /data/apache-tomcat-test1 && rm -rf lib/ bin/ && mkdir bin && cd -##复制启动和停止脚本到bin文件夹,带权限复制cp -p tomcat-start.sh tomcat-stop.sh /data/apache-tomcat-test1/bin/##一个同样的tomcat目录,带权限复制cp -Rp /data/apache-tomcat-test1/ /data/apache-tomcat-test2/ 配置 server.xml 端口
你知道的,同一个服务器部署不同 Tomcat 要设置不同的端口,不然会报端口冲突,所以我们只需要修改conf/server.xml中的其中前三个端口就行了。但它有四个分别是: - Server Port:该端口用于监听关闭tomcat的shutdown命令,默认为8005
- Connector HTTP Port:该端口用于监听HTTP的请求,默认为8080
- Connector AJP Port:该端口用于监听AJP( Apache JServ Protocol )协议上的请求,通常用于整合Apache Server等其他HTTP服务器,默认为8009
- Redirect Port:重定向端口,出现在Connector配置中,如果该Connector仅支持非SSL的普通http请求,那么该端口会把 https 的请求转发到这个Redirect Port指定的端口,默认为8443;
去掉注释的版本: <?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 "%r" %s %b" /> </Host> </Engine> </Service></Server> tomcat-test1改为: - Server Port:9015
- Connector HTTP Port:9010
- Connector AJP Port:9019
tomcat-test2改为: - Server Port:9025
- Connector HTTP Port:9020
- Connector AJP Port:9029
修改标识: echo "test1"> /data/apache-tomcat-test1/webapps/ROOT/index.jspecho "test2"> /data/apache-tomcat-test2/webapps/ROOT/index.jsp 修改完成,接着启动tomcat: /data/apache-tomcat-test1/bin/tomcat-start.sh/data/apache-tomcat-test2/bin/tomcat-start.sh 
curl的时候是比较慢的,因为还没启动完成。启动完之后就好了。 curl 127.0.0.1:9010curl 127.0.0.1:9020 这里注意访问端口是Connector HTTP Port 对应的端口 4、后记 其实搭起来不太难,经过参考文章的思路,就是公用一个tomcat的lib和bin,这样子升级的时候替换lib即可,bin都同一用CATALINA_HOME的脚本,其实CATALINA_HOME下的bin下的start和shutdown脚本统一调用了catalina.sh,而单机多实例的则是巧妙运用了catalina.sh是通过环境中的CATALINA_HOME和CATALINA_BASE变量启动tomcat的 ,通过改变CATALINA_BASE的路径达到同一条脚本启动tomcat在不同目录下 。 5、问题 5.1、tomcat启动慢
可以看到因为生成session ID用了1分06秒,太久了,导致应用deploying整体的时间大大增加,这个问题是可以解决的,可以再启动的时候增加jvm参数-Djava.security.egd=file:/dev/./urandom ,但是这样做应用产生随机数的能力被减弱,或者说随机不够均匀,对于经常使用加密的应用可能有安全影响。 修改一下启动脚本,添加了JAVA_OPTS的设置,能使用JAVA_OPTS,是因为catalina.sh会读出这个变量。 #!/bin/bash##这里的CATALINA_BASE,是当前脚本的的父目录,如果不在CATALINA_BASE的子目录的话,记得修改export CATALINA_BASE=$(cd $(dirname $0); cd .. ; pwd)echo $CATALINA_BASETOMCAT_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" ] ; thenecho "tomcat($TOMCAT_ID) still running now , please shutdown it first"; exit 2;fiTOMCAT_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_LOGfi 5.2、远程ssh时,环境变量不生效问题 使用source命令刷新当前环境变量。
具体修改如下: tomcat-start.sh :
#!/bin/bash##这里的CATALINA_BASE,是当前脚本的的父目录,如果不在CATALINA_BASE的子目录的话,记得修政source /etc/profileexport 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" ] ; thenecho "tomcat($TOMCAT_ID) still running now , please shutdown it first"; exit 2;fiTOMCAT_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_LOGfi tomcat-stop.sh
#!/bin/bash## 这里的CATALINA_BASE,是当前脚本的的父目录,如果不在CATALINA_BASE的子目录的话,记得修政source /etc/profileexport 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" ] ; thenTOMCAT_STOP_LOG=`$CATALINA_HOME/bin/shutdown.sh`else echo "Tomcat instance not found : $CATALINA_BASE" exitfiif [ "$?" = "0" ]; then echo "shell script: $0" echo "stop succeed!!!"else echo "$0 $CATALINA_BASE stop failed" echo "CATALINA_BASE: $CATALINA_BASE" echo $TOMCAT_STOP_LOGfi 附上restart脚本:
tomcat-restart.sh : #!/bin/bashsource /etc/profileexport CATALINA_BASE=$(cd $(dirname $0); cd .. ; pwd)GREEN_COLOR='/E[1;32m' #绿RES='/E[0m'TOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2}'`SLEEP_TIME=1echo "----------------------------------"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}"fiwhile [ -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.shecho -e "${GREEN_COLOR}---------------end startup-------------------${RES}" 参考博客: 聊聊 Tomcat 的单机多实例 Spring Boot应用首次启动慢的问题 下载地址: Tomcat的卸载和重装的实现(图文) 详解ubuntu安装opencv的正确方法 |