Tomcat多实例部署方案


1. 介绍

在工作中, 所有应用原本是使用IBM Websphere容器进行部署的, 然而IBM全家桶毕竟是收费的, 而且技术支持依赖人家. 所以有了改成tomcat容器部署的方案. 但在改造过程中, 项目组将改造的五六个应用分别构建成war包, 每个应用war包使用一个tomcat容器, 分配各自不同的http端口, 这样的方式也是没什么问题的.

​ 但就在2021年, 日志实现框架log4j2被爆出重量级的漏洞, 最终解决方案是升级官方发布的jar包版本. 那如果tomcat也出现这样的问题, 我们需要对每个应用的tomcat容器进行升级, 运维工作量可想而知. 有没有方案可以让这些应用共享一个tomcat容器, 并分配不同的http端口, 遇到问题只需要升级一个tomcat容器即可呢? 答案肯定是有的, 下面就给干货.

​ 解决思想就是只放置一个tomcat容器, 让多个子实例共享这个tomcat容器(主要是里面的lib), 然后在多个子实例中编写自己启动/关闭脚本, 实际还是调用父级tomcat的启动/关闭脚本; 以及编写自己的conf配置信息.

2. 环境准备

2.1 JDK8安装

将下载的jdk8压缩包解压到指定的安装目录.

# 解压jdk
tar -xvf jdk-8u141-linux-x64.tar.gz /usr/tomcat
# 修改jdk-8u141-linux-x64名称为jdk1.8.0.222
mv jdk-8u141-linux-x64 jdk1.8.0.222

在这里插入图片描述

配置jdk环境变量, vi /etc/profile

export JAVA_HOME=/usr/tomcat/jdk1.8.0.222
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar::$JAVA_HOME/lib/tools.jar

在这里插入图片描述

生效配置

source /etc/profile

2.2 父容器tomcat准备

首先下载一个tomcat, 解压到指定的安装目录.

# 解压tomcat
tar -xvf apache-tomcat-9.0.16.tar.gz /usr/tomcat/
# 修改apache-tomcat-9.0.16名称为base_tomcat
mv apache-tomcat-9.0.16 base_tomcat

在这里插入图片描述

进入base_tomcat, 可以看到里面的结构就是原本tomcat该有的那些目录, bin, lib, webapp, conf等, 我们后面要共享的就是base_tomcat这个父容器的lib, 且脚本也是指向的父容器bin里面的shell脚本进行启动和关闭. 父容器的conf里面的配置我们不做任何更改, 而是复制一份在各个子应用实例中进行配置修改.
在这里插入图片描述

查看conf目录下的配置文件项
在这里插入图片描述

3. 子应用实例准备

我先改造一个实例iems展示, 首先需要复制一份tomcat到父级容器的同级目录.

# # 解压tomcat
tar -xvf apache-tomcat-9.0.16.tar.gz /usr/tomcat/
# 修改apache-tomcat-9.0.16名称为iems
mv apache-tomcat-9.0.16 iems

因为后面是共享父容器的lib, 启动/关闭脚本, 所以需要将子实例中的lib下的jar包都删除, bin下面的shell脚本都删除.
在这里插入图片描述

进入iems, 按照上面步骤删除不需要的lib和shell脚本.

cd iems
# 删除lib
rm -rf lib
# 删除shell脚本
cd bin
rm -rf *.sh

在这里插入图片描述

因为删除了子实例的脚本, 如果这样部署, 应用是无法调用到tomcat的启动脚本的. 需要我们自定义脚本来调用父容器tomcat的脚本. 我这里自定义了三个脚本,分别为 setenv.sh ,startup.sh, shutdown.sh.

touch setenv.sh
touch shutdown.sh
touch startup.sh

在这里插入图片描述

编辑 setenv.sh, 主要是环境变量, JVM相关的参数配置.
在这里插入图片描述

编辑 startup.sh, 指向父tomcat的启动脚本.

CATALINA_HOME是父容器tomcat的目录, /usr/tomcat/base_tomcat

CATALINA_BASE就是当前子实例的目录, /usr/tomcat/iems
在这里插入图片描述

编辑shutdown.sh, 指向父tomcat的关闭脚本.

在这里插入图片描述

4. 子应用实例配置修改

4.1 修改server.xml

<?xml version="1.0" encoding="UTF-8"?>
<Server port="9067" shutdown="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">
     <!--http端口配置-->
    <Connector port="9087" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8467" />
      
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8467" />
    <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>

http端口配置内容, http端口修改为9087
在这里插入图片描述

4.2 修改tomcat-users.xml

tomcat控制台的应用管理界面访问需要用户/密码, 这里可以配置添加用户/密码. tomcat/123456

<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">

  <role rolename="manager-gui"/>
  <role rolename="manager-script"/>
  <role rolename="manager-status"/>  
  <role rolename="manager-jmx"/>  
  <role rolename="admin-gui"/> 
  <role rolename="admin-script"/> 
  <user username="tomcat" password="123456" roles="manager-gui,manager-script,manager-status,manager-jmx,admin-gui,admin-script"/>
</tomcat-users>

在这里插入图片描述

4.3 修改catalina.properties

一些属性配置可以添加在这个文件中, 比如数据库连接信息, 共享库设置, 配置环境指定等.

package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.
package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,\
org.apache.jasper.,org.apache.naming.,org.apache.tomcat.

common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"

# application-{profile}.properties中的配置都可以在这里配置,且优先级高于应用里的配置.
# 设置配置环境参数, 启动应用将会读取application-{profile}.properties文件的配置
spring.profiles.active=uat

server.loader=
# 共享库lib配置,这个是应用要使用到的jar包目录,不需要可以注释掉
# 如果将war包中的lib抽取到公共目录下面,可以在这里配置读取
shared.loader=/usr/tomcat/sharelib/iemslib/*.jar

tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
annotations-api.jar,\
ant-junit*.jar,\
ant-launcher.jar,\
ant.jar,\
asm-*.jar,\
aspectj*.jar,\
bootstrap.jar,\
catalina-ant.jar,\
catalina-ha.jar,\
catalina-jmx-remote.jar,\
catalina-storeconfig.jar,\
catalina-tribes.jar,\
catalina-ws.jar,\
catalina.jar,\
cglib-*.jar,\
cobertura-*.jar,\
commons-beanutils*.jar,\
commons-codec*.jar,\
commons-collections*.jar,\
commons-daemon.jar,\
commons-dbcp*.jar,\
commons-digester*.jar,\
commons-fileupload*.jar,\
commons-httpclient*.jar,\
commons-io*.jar,\
commons-lang*.jar,\
commons-logging*.jar,\
commons-math*.jar,\
commons-pool*.jar,\
dom4j-*.jar,\
easymock-*.jar,\
ecj-*.jar,\
el-api.jar,\
geronimo-spec-jaxrpc*.jar,\
h2*.jar,\
hamcrest-*.jar,\
hibernate*.jar,\
httpclient*.jar,\
icu4j-*.jar,\
jasper-el.jar,\
jasper.jar,\
jaspic-api.jar,\
jaxb-*.jar,\
jaxen-*.jar,\
jdom-*.jar,\
jetty-*.jar,\
jmx-tools.jar,\
jmx.jar,\
jsp-api.jar,\
jstl.jar,\
jta*.jar,\
junit-*.jar,\
junit.jar,\
log4j*.jar,\
mail*.jar,\
objenesis-*.jar,\
oraclepki.jar,\
oro-*.jar,\
servlet-api-*.jar,\
servlet-api.jar,\
slf4j*.jar,\
taglibs-standard-spec-*.jar,\
tagsoup-*.jar,\
tomcat-api.jar,\
tomcat-coyote.jar,\
tomcat-dbcp.jar,\
tomcat-i18n-cs.jar,\
tomcat-i18n-de.jar,\
tomcat-i18n-en.jar,\
tomcat-i18n-es.jar,\
tomcat-i18n-fr.jar,\
tomcat-i18n-ja.jar,\
tomcat-i18n-ko.jar,\
tomcat-i18n-pt-BR.jar,\
tomcat-i18n-ru.jar,\
tomcat-i18n-zh-CN.jar,\
tomcat-jdbc.jar,\
tomcat-jni.jar,\
tomcat-juli-adapters.jar,\
tomcat-juli.jar,\
tomcat-util-scan.jar,\
tomcat-util.jar,\
tomcat-websocket.jar,\
tools.jar,\
websocket-api.jar,\
wsdl4j*.jar,\
xercesImpl.jar,\
xml-apis.jar,\
xmlParserAPIs-*.jar,\
xmlParserAPIs.jar,\
xom-*.jar

tomcat.util.scan.StandardJarScanFilter.jarsToScan=\
log4j-taglib*.jar,\
log4j-web*.jar,\
log4javascript*.jar,\
slf4j-taglib*.jar

# String cache configuration.
tomcat.util.buf.StringCache.byte.enabled=true
#tomcat.util.buf.StringCache.char.enabled=true
#tomcat.util.buf.StringCache.trainThreshold=500000
#tomcat.util.buf.StringCache.cacheSize=5000

4.4 部署应用

将构建好的war包(iems.war)放到子实例的webapps目录即可.
在这里插入图片描述

然后进入bin目录启动子实例iems.

cd /usr/tomcat/iems/bin
./startup.sh
# 查看启动日志, 也可以看自己应用的logback中指定的日志文件
tail -f /usr/tomcat/iems/logs/catalina.out

启动成功后, 进入iems的控制台查看. 浏览器访问http://{ip}:{port}/
在这里插入图片描述
使用用户名/密码登录进入应用管理界面(Manager App), 查看应用部署情况. tomcat/123456
在这里插入图片描述

输入用户密码后, 登录进入应用发布界面, 可以看到我们的bmws_iems应用已经启动成功, 这个界面着实很丑.

下面还有读取本地war包发布的功能.
在这里插入图片描述

5. tomcat监控插件

上面提到tomcat控制台的应用发布界面真的很丑, 功能也很少. 我从网上找到了一款tomcat监控插件, 对tomcat管理应用扩展了很多功能. Tomcat监控工具之probe

直接用起来, 在GitHub下载 probe , 下载完解压到tomcat子实例的webapps目录下即可, 不用修改任何配置, 即插即用. 现在我们重新启动iems子实例看看. 浏览器访问http://{ip}:{port}/probe

在这里插入图片描述

我们来看看proble扩展了那些好用的功能.

应用卸载, 停止, 重启
在这里插入图片描述

发布或更新应用, 并可以设置上下文根context名称, 启动解压后的目录名称就是上下文根context的名称.

在这里插入图片描述

查看子实例的系统信息, 支持手动垃圾回收.
在这里插入图片描述

QPS监控
在这里插入图片描述
支持语言切换
在这里插入图片描述

6. 遇到的问题

项目上线前, 在准备验证报文的过程中, 发现浏览器直发报文请求应用会报错, 但是使用postman等测试工具发送请求正常. 由于生产环境没有提供postman这类测试工具给我们验证, 所以必须解决这个问题. 经过查阅资料, 需要修改一些配置才能支持url自动encoding编码.

在catalina.properties文件中加入编码配置

tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true

在这里插入图片描述

在server.xml文件的中添加编码配置

<Connector port="9087" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8467" 
               relaxedPathChars="|{}[],"
                  relaxedQueryChars="|{}[],"
  />

在这里插入图片描述


文章作者: 王子
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 王子 !
评论
  目录