# Tomcat

Tomcat

安装Tomcat

  • JDK https://www.oracle.com/java/technologies/downloads/archive/
  • OpenJDK https://jdk.java.net/21/ 或 https://learn.microsoft.com/zh-cn/java/openjdk/download
  • Tomcat https://tomcat.apache.org/
  • 注意:Tomcat/conf/startup.sh 配置文件错误时不会报错。Tomcat/conf/shutdown.sh 重复关闭时会报错。
// 安装Tomcat
Tomcat服务器(192.168.88.88Tomcat目录为/usr/local/tomcat):
]# ls apache-tomcat-8.0.30.tar.gz 
	apache-tomcat-8.0.30.tar.gz
]# yum install -y java-1.8.0-openjdk-devel		// Tomcat使用Java开发,依赖包含java-1.8.0-openjdk
]# tar -xf apache-tomcat-8.0.30.tar.gz
]# mv apache-tomcat-8.0.30 /usr/local/tomcat	// 解压即用
]# cd /usr/local/tomcat
tomcat]# bin/startup.sh 						// 配置文件错误时不会报错,需手动检验是否成功开启		
tomcat]# ss -ntulp | grep java
    tcp   LISTEN 0      100                     *:8080            *:*    users:(("java",pid=1424,fd=48)) 	// HTTP端口
    tcp   LISTEN 0      1      [::ffff:127.0.0.1]:8005            *:*    users:(("java",pid=1424,fd=78)) 	// 关闭服务端口
    tcp   LISTEN 0      100                     *:8009            *:*    users:(("java",pid=1424,fd=53)) 	// AJP端口
	// Tomcat启动需要从/dev/random读取大量的随机数据,若启动速度较慢,可以创建软连接`ln -s /dev/urandom /dev/random`,否则可能由于/dev/random随机数据不足而导致的虽然监听端口但无法正常提供服务
tomcat]# mv /dev/random{,.ori}
tomcat]# ln -s /dev/urandom /dev/random
tomcat]# bin/shutdown.sh
tomcat]# bin/startup.sh 

tomcat]# ls
	bin  conf  lib  LICENSE  logs  NOTICE  RELEASE-NOTES  RUNNING.txt  temp  webapps  work
tomcat]# bin/version.sh 
    Using CATALINA_BASE:   /usr/local/tomcat
    Using CATALINA_HOME:   /usr/local/tomcat
    Using CATALINA_TMPDIR: /usr/local/tomcat/temp
    Using JRE_HOME:        /usr
    Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
    Server version: Apache Tomcat/8.0.30
    Server built:   Dec 1 2015 22:30:46 UTC
    Server number:  8.0.30.0
    OS Name:        Linux
    OS Version:     4.18.0-372.9.1.el8.x86_64
    Architecture:   amd64
    JVM Version:    1.8.0_332-b09
    JVM Vendor:     Red Hat, Inc.
tomcat]# java -version
    openjdk version "1.8.0_332"
    OpenJDK Runtime Environment (build 1.8.0_332-b09)
    OpenJDK 64-Bit Server VM (build 25.332-b09, mixed mode)
tomcat]# cp conf/server.xml{,.default}

systemd.service

  • https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html
// 创建tomcat.service

// 情况一:YUM安装jdk或openjdk
[root@tomcat ~]# which java
	/usr/bin/java
[root@tomcat ~]# cat /usr/lib/systemd/system/tomcat.service
    #/usr/lib/systemd/system/tomcat.service
    [Unit]
    Description=Tomcat Service
    After=network-online.target remote-fs.target nss-lookup.target
    Wants=network-online.target

    [Service]
    Type=forking
    ExecStart=/usr/local/tomcat/bin/startup.sh
    ExecStop=/usr/local/tomcat/bin/shutdown.sh
    ExecReload=/usr/local/tomcat/bin/startup.sh && sleep 2 && /usr/local/tomcat/bin/shutdown.sh

    [Install]
    WantedBy=multi-user.target
[root@tomcat ~]# systemctl daemon-reload

// 情况二:自定义安装jdk或openjdk
[root@tomcat ~]# tar -xf jdk-8u361-linux-x64.tar.gz
[root@tomcat ~]# ln -s /root/jdk1.8.0_361/ /usr/local/jdk
[root@tomcat ~]# cat /etc/sysconfig/tomcat
    JAVA_HOME=/usr/local/jdk
    PATH=/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:${JAVA_HOME}/bin:${JAVA_HOME}/jre/bin
    CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
[root@tomcat ~]# cat /usr/lib/systemd/system/tomcat.service
    #/usr/lib/systemd/system/tomcat.service
    [Unit]
    Description=Tomcat Service
    After=network-online.target remote-fs.target nss-lookup.target
    Wants=network-online.target

    [Service]
    Type=forking
	EnvironmentFile=/etc/sysconfig/tomcat
    ExecStart=/usr/local/tomcat/bin/startup.sh
    ExecStop=/usr/local/tomcat/bin/shutdown.sh
    ExecReload=/usr/local/tomcat/bin/startup.sh && sleep 2 && /usr/local/tomcat/bin/shutdown.sh

    [Install]
    WantedBy=multi-user.target
[root@tomcat ~]# systemctl daemon-reload

// 验证
[root@tomcat ~]# systemctl enable tomcat.service --now
	Created symlink /etc/systemd/system/multi-user.target.wants/tomcat.service → /usr/lib/systemd/system/tomcat.service.
[root@tomcat ~]# ss -ntulp |grep java
    tcp   LISTEN 0      1      [::ffff:127.0.0.1]:8005            *:*    users:(("java",pid=1734,fd=77)) 
    tcp   LISTEN 0      100                     *:8009            *:*    users:(("java",pid=1734,fd=53)) 
    tcp   LISTEN 0      100                     *:8080            *:*    users:(("java",pid=1734,fd=48))

注意:使用systemctl启动的不能使用路径关闭,使用路径启动的不能使用systemctl关闭

管理端网页

// 设置管理端网页。但生产环境中为安全一般禁用
Tomcat服务器(192.168.88.88Tomcat目录为/usr/local/tomcat):

浏览器访问 http://192.168.88.88:8080
可以通过Server StatusManager AppHost Manager管理Tomcat
Tomcat 8.5以后,默认只能本地环回地址访问127.0.0.1

// 开启功能并设置用户密码
[root@tomcat tomcat]# vim conf/tomcat-users.xml 		// 管理网页配置文件
     39   <role rolename="manager-gui"/>					# 开启功能
     40   <role rolename="admin-gui"/>						# 开启功能
     41   <user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>	# 设置用户密码
     42 </tomcat-users>
[root@tomcat tomcat]# bin/shutdown.sh 
[root@tomcat tomcat]# bin/startup.sh 

// Tomcat 8.5默认限制管理端的访问IP
[root@tomcat tomcat]# curl -u tomcat:tomcat http://127.0.0.1:8080/manager/status
[root@tomcat tomcat]# curl -u tomcat:tomcat http://127.0.0.1:8080/host-manager/html
[root@tomcat tomcat]# curl -u tomcat:tomcat http://127.0.0.1:8080/host-manager/html	 // 403
// 修改访问IP的限制,不是Tomcat的配置文件所以修改后不用重启服务
[root@tomcat tomcat]# find . -name context.xml
    ./conf/context.xml
    ./webapps/host-manager/META-INF/context.xml
    ./webapps/manager/META-INF/context.xml
[root@tomcat tomcat]# less webapps/host-manager/META-INF/context.xml
      <Valve className="org.apache.catalina.valves.RemoteAddrValve"
             allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />		# 8.5版本之后限制只能通过127.0.0.1访问
[root@tomcat tomcat]# less webapps/manager/META-INF/context.xml 
      <Valve className="org.apache.catalina.valves.RemoteAddrValve"
             allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />		# 8.5版本之后限制只能通过127.0.0.1访问

[root@tomcat tomcat]# sed -i 's,"127,"\\d,' webapps/host-manager/META-INF/context.xml webapps/manager/META-INF/context.xml
[root@tomcat tomcat]# curl -u tomcat:tomcat http://127.0.0.1:8080/host-manager/html	 // 正常

// 生产环境中禁用管理端网页
[root@tomcat tomcat]# vim conf/server.xml		// 注释或删除conf/tomcat-users.xml相关的配置
      <!--
      <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>
      -->
[root@tomcat tomcat]# bin/shutdown.sh 
[root@tomcat tomcat]# bin/startup.sh 
[root@tomcat tomcat]# curl -u tomcat:tomcat http://127.0.0.1:8080/host-manager/html	 // 404

主配置文件server.xml

[root@tomcat tomcat]# cat conf/server.xml		# 去除注释之后的有效内容
<?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>
  <!-- <GlobalNamingResources>是tomcat-users.xml的相关配置,生产环境中注释或删除-->
  <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">
        					<!-- defaultHost指定默认的虚拟主机 -->
      <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">
      <!-- <Host>虚拟主机,name域名,appBase网页目录,unpackWARs是否自动解WAR包,autoDeploy是否自动部署(加载到jvm中)-->
        <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" />
        <!-- directory访问日志目录,prefix访问日志前缀,suffix访问日志后缀,pattern访问日志内容格式
             这里&quot;是双引号,已经使用了一层双引号
             如果增加内容并想使用双引号:pattern="%h %l %u %t &quot;%r&quot; %s %b &quot;%{User-Agent}i&quot;" -->
      </Host>
    </Engine>
  </Service>
</Server>

8005是shutdown端口:`telnet 127.0.0.1 8005`后输入SHUTDOWN
8080是HTTP端口
8443是HTTPS端口,默认关闭
8009是AJP端口,用于tomcat和apache的交互,8.5版本后默认关闭

Tomcat处理用户请求的流程:
用户发出请求——》请求达到Tomcat——》<Connector>处理http请求——》交给<Engine>的虚拟主机<Host>处理——》处理完成返回给用户

日志格式

访问日志内容的格式TomcatNginx
客户端IP地址%h$remote_addr
用户名%l
用户名%u
日期和时间%t$local_time
用户请求的起始行(请求方法和URI)%r$request
状态码%s$status
服务端响应的大小%b$body_bytes_sent
用户从哪里跳转来的%{Referer}i$http_referer
用户的客户端%{User-Agent}i$http_user_agent
用户的真实IP地址%{X-Forwarded-For}i$http_x_forwarded_for

虚拟主机<Host>

  • <Engine> 中的 <Host> 中的参数:
    • name:虚拟主机名称,也是域名。
    • appBase:网页目录。
    • unpackWARs:是否自动解WAR包,默认为true。
    • autoDeploy:是否自动部署,默认为true。
  • 注意:如果配置了[降权启动](# 降权启动(监牢模式)),那么要修改数据的所有者所属组。
// 虚拟主机<Host>
Tomcat服务器(192.168.88.88Tomcat目录为/usr/local/tomcat):
// 配置
[root@tomcat tomcat]# cp server.xml{.default,}
[root@tomcat tomcat]# vim conf/server.xml				// 在<Engine>添加两个虚拟主机
    <Engine name="Catalina" defaultHost="localhost">
      <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>
      <Host name="www.a.com"  appBase="test_a"		
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="test_logs"
               prefix="test_access_log" suffix=".log"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      <Host name="www.b.com"  appBase="test_b"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="test_logs"
               prefix="test_access_log" suffix=".log"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
    </Engine>
[root@tomcat tomcat]# bin/shutdown.sh > /dev/null
[root@tomcat tomcat]# bin/startup.sh > /dev/null
// 创建index.jsp。注意:如果部署了降权启动(假设运行用户为tomcat),那么要修改数据的所有者所属组
[root@tomcat tomcat]# mkdir -p test_{a,b}/ROOT
[root@tomcat tomcat]# mkdir test_logs
[root@tomcat tomcat]# echo 'test_a~~' > test_a/ROOT/index.jsp
[root@tomcat tomcat]# echo 'test_b~~' > test_b/ROOT/index.jsp

注意:如果部署了降权启动(假设运行用户为tomcat),那么要修改数据的所有者所属组

// 验证
客户端(192.168.88.5):
[root@client ~]# echo '192.168.88.88 www.a.com www.b.com' >> /etc/hosts
[root@client ~]# curl www.a.com:8080
	test_a~~
[root@client ~]# curl www.b.com:8080
	test_b~~

[root@tomcat tomcat]# cat test_logs/test_access_log.2023-10-25.log 
    192.168.88.5 - - [25/Oct/2023:18:58:41 +0800] "GET / HTTP/1.1" 200 9
    192.168.88.5 - - [25/Oct/2023:18:58:45 +0800] "GET / HTTP/1.1" 200 9

访问路径<Context>

  • 注意:如果配置了[降权启动](# 降权启动(监牢模式)),那么要修改数据的所有者所属组。
  • <Engine> 中的 <Host> 中的属性 appBase 的使用:
    • 不定义appBase,指向 Tomcat/webapps
    • appBase="",指向 Tomcat/
    • appBase="相对路径",指向 Tomcat/相对路径
    • appBase="绝对路径",指向 绝对路径/
<Host>属性appBase
不使用<Context>
IP地址:8080IP地址:8080/test/,这里test是目录IP地址:8080/test,这里test是文件
不定义,为webappswebapps/ROOT/index.jspwebapps/test/index.jspwebapps/ROOT/test
""ROOT/index.jsptest/index.jspROOT/test
相对路径 "app"app/ROOT/index.jspapp/test/index.jspapp/ROOT/test
绝对路径 "/app"/app/ROOT/index.jsp/app/test/index.jsp/app/ROOT/test
  • <Engine> 中的 <Host> 中的 <Context path="/字符串A" docBase="字符串B" />
    • 属性 path(精确匹配,支持*?)的使用:只有当客户端访问的URI匹配path时,<Context>才配置生效
      • path的值可以为空"",也可以为"/路径"(必须以/开头且不能以/结尾)
        - 当path为空""时,可以不定义docBase。此时,只有匹配不含目录的URI,<Context>才配置生效
        • 当path不为空"/路径"时,就必须定义docBase。此时,只有URI匹配"/路径"时,<Context>才配置生效
      • 定义了appBase,就必须定义path。即,在<Context>中,属性path是必须的。
  • path=""时,只匹配不含目录的URI。
<Context>属性path
(假设appBase=“app”)
<Context>属性docBaseIP地址:8080IP地址:8080/test,
这里test是文件
IP地址:8080/test/,
这里test是目录
IP地址:8080/test/abc,
path=""不匹配包含目录的URI
""不定义,为ROOTapp/ROOT/index.jspapp/ROOT/testapp/test/index.jspapp/test/abc
""""app/index.jspapp/testapp/test/index.jspapp/test/abc
""相对路径 "doc"app/doc/index.jspapp/doc/testapp/test/index.jspapp/test/abc
""绝对路径 "/doc"/doc/index.jsp/doc/testapp/test/index.jspapp/test/abc
  • path="/字符串A"时,字符串匹配URI。
<Context>属性path
(假设appBase=“app”)
<Context>属性docBaseIP地址:8080/pa/IP地址:8080/pa/test/,
这里test是目录
IP地址:8080/pa/test,
这里test是文件
绝对路径 "/pa"""app/index.jspapp/test/index.jspapp/test
绝对路径 "/pa"相对路径 "doc"app/doc/index.jspapp/doc/test/index.jspapp/doc/test
绝对路径 "/pa"绝对路径 "/doc"/doc/index.jsp/doc/test/index.jsp/doc/test
// 访问路径
appBase的使用:
- 不定义appBase,指向 Tomcat/webapps
- appBase="",指向 Tomcat/
- appBase="相对路径",指向 Tomcat/相对路径
- appBase="绝对路径",指向 绝对路径

path(精确匹配,支持*?)的使用:只有当客户端访问的URI匹配path时,<Context>才配置生效
- path的值可以为空"",也可以为"/路径"(必须以`/`开头且不能以`/`结尾)
	org.apache.catalina.core.StandardContext.setPath A context path must either be an empty string or start with a '/' and do not end with a '/'. 
    - 当path为空""时,可以不定义docBase。此时,只有匹配不含目录的URI<Context> 才生效。
    - 当path不为空"/路径"时,就必须定义docBase。此时,只有URI匹配"/路径"时,<Context> 才生效。
- 定义了appBase,就必须定义path。


Tomcat服务器(192.168.88.88Tomcat目录为/usr/local/tomcat):
// 配置
[root@tomcat tomcat]# \cp server.xml{.default,}
[root@tomcat tomcat]# vim conf/server.xml		// 配置虚拟主机localhost、tapp{,0,1,2}、tpa{,0,1,2}、tth{0,1,2}
    <Engine name="Catalina" defaultHost="localhost">
      <Host name="localhost"  appBase="app"		# 192.168.88.88:80 ——》app/ROOT/index.jsp
            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>

  <!-- appBase-->
      <Host name="tapp"  >						# tapp:8080 ——》webapps/ROOT/index.jsp
      </Host>
      <Host name="tapp0"  appBase="">			# tapp0:8080 ——》ROOT/index.jsp
      </Host>
      <Host name="tapp1"  appBase="app">		# tapp1:8080 ——》app/ROOT/index.jsp
      </Host>
      <Host name="tapp2"  appBase="/app">		# tapp2:8080 ——》/app/ROOT/index.jsp
      </Host>

  <!-- path="",可以不定义appBase-->
      <Host name="tpa"  appBase="app">			# tpa:8080 ——》app/ROOT/index.jsp
            <Context path="" />		
      </Host>
      <Host name="tpa0"  appBase="app">			# tpa0:8080 ——》app/index.jsp
            <Context path="" docBase="" />
      </Host>
      <Host name="tpa1"  appBase="app">			# tpa1:8080 ——》app/doc/index.jsp
            <Context path="" docBase="doc" />
      </Host>
      <Host name="tpa2"  appBase="app">			# tpa2:8080 ——》/doc/index.jsp
            <Context path="" docBase="/doc" />
      </Host>

  <!-- path="/pa",必须定义appBase-->
      <Host name="tth0"  appBase="app">			# tth0:8080/pa/ ——》app/index.jsp,tth0:8080/pa/test/ ——》app/test/index.jsp
            <Context path="/pa" docBase="" />
      </Host>
      <Host name="tth1"  appBase="app">			# tth1:8080/pa/ ——》app/doc/index.jsp,tth1:8080/pa/test/ ——》app/doc/test/index.jsp
            <Context path="/pa" docBase="doc" />
      </Host>
      <Host name="tth2"  appBase="app">			# tth2:8080/pa/ ——》/doc/index.jsp,tth2:8080/pa/test/ ——》/doc/test/index.jsp
            <Context path="/pa" docBase="/doc" />
      </Host>
    </Engine>
[root@tomcat tomcat]# systemc restart tomcat.service
// 创建index.jsp。注意:如果部署了降权启动(假设运行用户为tomcat),那么要修改数据的所有者所属组
[root@tomcat tomcat]# mkdir -p ROOT
[root@tomcat tomcat]# mkdir -p app/{ROOT,doc}
[root@tomcat tomcat]# mkdir -p /app/ROOT
[root@tomcat tomcat]# mkdir -p /doc/ROOT
[root@tomcat tomcat]# echo 'webapps/ROOT/index.jsp' > webapps/ROOT/index.jsp
[root@tomcat tomcat]# echo 'ROOT/index.jsp' > ROOT/index.jsp
[root@tomcat tomcat]# echo 'app/index.jsp' > app/index.jsp
[root@tomcat tomcat]# echo 'app/ROOT/index.jsp' > app/ROOT/index.jsp
[root@tomcat tomcat]# echo 'app/doc/index.jsp' > app/doc/index.jsp
[root@tomcat tomcat]# echo '/app/ROOT/index.jsp' > /app/ROOT/index.jsp
[root@tomcat tomcat]# echo '/doc/index.jsp' > /doc/index.jsp
[root@tomcat tomcat]# echo '/doc/ROOT/index.jsp' > /doc/ROOT/index.jsp
[root@tomcat tomcat]# mkdir app/test app/doc/test /doc/test
[root@tomcat tomcat]# echo 'app/test/index.jsp' > app/test/index.jsp
[root@tomcat tomcat]# echo 'app/doc/test/index.jsp' > app/doc/test/index.jsp
[root@tomcat tomcat]# echo '/doc/test/index.jsp'> /doc/test/index.jsp

客户端:
[root@client ~]# echo '192.168.88.88 tapp tapp0 tapp1 tapp2' >> /etc/hosts
[root@client ~]# echo '192.168.88.88 tpa tpa0 tpa1 tpa2' >> /etc/hosts
[root@client ~]# echo '192.168.88.88 tth0 tth1 tth2' >> /etc/hosts
[root@client ~]# curl 192.168.88.88:8080
	app/ROOT/index.jsp

// 1.验证appBase的使用
[root@client ~]# curl tapp:8080
	app/ROOT/index.jsp
[root@client ~]# curl tapp0:8080
	ROOT/index.jsp
[root@client ~]# curl tapp1:8080
	webapps/ROOT/index.jsp
[root@client ~]# curl tapp2:8080
	/app/ROOT/index.jsp

// 2.验证path=""
[root@client ~]# curl tpa:8080
	app/ROOT/index.jsp
[root@client ~]# curl tpa0:8080
	app/index.jsp
[root@client ~]# curl tpa1:8080
	app/doc/index.jsp
[root@client ~]# curl tpa2:8080
	/doc/index.jsp

// 3.验证path="/pa"
// 3.1.不匹配path则<Context>不生效
[root@client ~]# curl tth0:8080
	app/ROOT/index.jsp
[root@client ~]# curl tth1:8080
	app/ROOT/index.jsp
[root@client ~]# curl tth2:8080
	app/ROOT/index.jsp

// 3.2.匹配path时<Context>才生效。注意:以`/`结尾则默认为目录,返回该目录下的index.jsp。没有以`/`结尾则为文件,返回该文件。
// 3.2.1.以`/`结尾则默认为目录,返回该目录下的index.jsp
[root@client ~]# curl tth0:8080/pa/
	app/index.jsp
[root@client ~]# curl tth1:8080/pa/
	app/doc/index.jsp
[root@client ~]# curl tth2:8080/pa/
	/doc/index.jsp
[root@client ~]# curl tth0:8080/pa/test/
	app/test/index.jsp
[root@client ~]# curl tth1:8080/pa/test/
	app/doc/test/index.jsp
[root@client ~]# curl tth2:8080/pa/test/
	/doc/test/index.jsp
// 3.2.2.没有以`/`结尾则为文件,返回该文件。
[root@client ~]# curl tth0:8080/pa
[root@client ~]# curl tth1:8080/pa
[root@client ~]# curl tth2:8080/pa
[root@client ~]# curl tth0:8080/pa/test
[root@client ~]# curl tth1:8080/pa/test
[root@client ~]# curl tth2:8080/pa/test

SSL

// SSL(https,8443)
keytool -genkeypair -alias 密钥对别名 -keyalg RSA -keystore 密钥库文件
* keytool命令由jdk提供
* 选项-genkeypair是keytool的选项,用于生成密钥对并存储在密钥库文件中
	* 选项-alias是-genkeypair的子选项,定义密钥对别名
	* 选项-keyalg是-genkeypair的子选项,指定生成密钥对使用的算法
	* 选项-keystore是-genkeypair的子选项,指定存储密钥对的密钥库文件
注意:一个密钥库文件中可以有多个密钥对。
在配置TomcatSSL时,
	必须:关键字keystoreFile指定密钥库文件,关键字keystorePass指定密钥库文件密码
	选用:关键字keyAlias指定密钥库文件中的密钥对(省略默认为第一个密钥对),关键字keyPass指定密钥对密码(省略默认同keystorePass)

Tomcat服务器(192.168.88.88Tomcat目录为/usr/local/tomcat):
// 创建密钥对
[root@tomcat tomcat]# keytool -genkeypair -alias testkey -keyalg RSA -keystore key
    Enter keystore password:  								// 设置密钥库文件密码
    Re-enter new password:  								// 重复密码
    What is your first and last name?
      [Unknown]:  xingming
    What is the name of your organizational unit?
      [Unknown]:  gongsi
    What is the name of your organization?
      [Unknown]:  bumen
    What is the name of your City or Locality?
      [Unknown]:  shi
    What is the name of your State or Province?
      [Unknown]:  sheng
    What is the two-letter country code for this unit?
      [Unknown]:  zh
    Is CN=xingming, OU=gongsi, O=bumen, L=shi, ST=sheng, C=zh correct?
      [no]:  y

    Enter key password for <testkey>						// 设置密钥对密码,回车同密钥库文件密码
            (RETURN if same as keystore password):  
    Re-enter new password: 									// 重复密码

    Warning:
    The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore key -destkeystore key -deststoretype pkcs12".
// 配置Tomcat
[root@tomcat tomcat]# echo 'webapps/ROOT/index.jsp' > webapps/ROOT/index.jsp
[root@tomcat tomcat]# \cp conf/server.xml.default conf/server.xml
[root@tomcat tomcat]# vim conf/server.xml
     85     <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
     86                maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
     87                clientAuth="false" sslProtocol="TLS"
     88                keystoreFile="/usr/local/tomcat/key" // keystoreFile指定密钥库文件位置,相对路径是Tomcat/
     89                keystorePass="123456"				// keystorePass指定密钥库文件密码
	 90				   keyAlias="testkey"					// keyAlias指定密钥库文件中的密钥对,省略默认为第一个密钥对
     91                keyPass="123456" />					// keyPass指定密钥对密码,省略默认同密钥库文件密码
[root@tomcat tomcat]# systemctl restart tomcat.service

客户端:
[root@client ~]# curl -k https://192.168.88.88:8443
	webapps/ROOT/index.jsp

解析动态网站

// 解析动态网站
Tomcat服务器(192.168.88.88Tomcat目录为/usr/local/tomcat):
浏览器访问 https://www.zrlog.com/ 下载war包

[root@tomcat tomcat]# ls ~/zrlog-2.2.1-efbe9f9-release.war
	/root/zrlog-2.2.1-efbe9f9-release.war
[root@tomcat tomcat]# cp ~/zrlog-2.2.1-efbe9f9-release.war webapps/zrlog.war
[root@tomcat tomcat]# ss -ntulp | grep 8080
	tcp   LISTEN 0      100                     *:8080            *:*    users:(("java",pid=1460,fd=48)) 
[root@tomcat tomcat]# ls webapps/
	docs  examples  host-manager  manager  ROOT  zrlog  zrlog.war

浏览器访问 http://192.168.88.88:8080/zrlog/,跳转 http://192.168.88.88:8080/zrlog/install/ 选择数据库并安装使用。论坛的文章存储在数据库,图片存储在本地网页目录

Tomcat多实例

// 多实例,在一台服务器运行多个tomcat服务,通过端口区分服务
nginx需要安装使用,可以通过导入配置文件来配置管理多个网站。Tomcat直接解压即用,可以在配置文件中配置多个网站,也可以直接通过多实例来配置管理多个网站。
Tomcat中配置多个虚拟主机:共享一个Tomcat进程和线程池,集中管理维护,共同启动停止。
Tomcat多实例:每一个Tomcat实例启动一个独立的进程和线程池,管理和维护相对独立,单独启动、停止。

// 思路
Tom多实例:已经部署好webapps/zrlog
1.共用jdk环境
2.复制多份tomcat并修改每个tomcat的端口(8080,8005,8443):tomcat_8081 tomcat_8082
3.指定不同的代码目录(推荐每个代码放在tomcat 默认的webapps/ROOT)
tomcat
    conf/server.xml(8080,8005)
    webapps/zrlog
tomcat_8081
    conf/server.xml(8081,8006)
    webapps/zrlog
tomcat_8082
    conf/server.xml(8082,8007)
    webapps/zrlog

// 部署
Tomcat服务器(192.168.88.88Tomcat目录为/usr/local/tomcat):
[root@tomcat ]# cd /usr/local
[root@tomcat local]# cp -r tomcat/ tomcat_8081
[root@tomcat local]# cp -r tomcat/ tomcat_8082
[root@tomcat local]# sed -i 's#8080#8081#g' tomcat_8081/conf/server.xml
[root@tomcat local]# sed -i 's#8005#8006#g' tomcat_8081/conf/server.xml
[root@tomcat local]# sed -i 's#8080#8082#g' tomcat_8082/conf/server.xml
[root@tomcat local]# sed -i 's#8005#8007#g' tomcat_8082/conf/server.xml
[root@tomcat local]# grep -P 'port="\d+"' tomcat_808*/conf/server.xml
    tomcat_8081/conf/server.xml:<Server port="8006" shutdown="SHUTDOWN">
    tomcat_8081/conf/server.xml: <Connector port="8081" protocol="HTTP/1.1"
    tomcat_8082/conf/server.xml:<Server port="8007" shutdown="SHUTDOWN">
    tomcat_8082/conf/server.xml: <Connector port="8082" protocol="HTTP/1.1"
[root@tomcat local]# tomcat/bin/startup.sh
[root@tomcat local]# tomcat_8081/bin/startup.sh
[root@tomcat local]# tomcat_8082/bin/startup.sh

此时,在192.168.88.88:8080/zrlog/192.168.88.88:8081/zrlog/192.168.88.88:8082/zrlog/ 上发表文章,文字存储在同一数据库,图片存储在Tomcat本地目录,可以使用挂载存储服务器,实现静态数据的一致。

监控Java应用

// 监控Java应用
// 命令行工具(由openjdk-devel或jdk-devel提供)
    jps -lvm
    jmap PID		:查看jvm信息、内存信息
    jstack PID		:查看进程信息
    jstat -gc PID	:查看进程信息

Tomcat服务器(192.168.88.88Tomcat目录为/usr/local/tomcat):
[root@tomcat ~]# jps
    2018 Bootstrap
    2613 Jps
[root@tomcat ~]# jps -l
    2625 sun.tools.jps.Jps
    2018 org.apache.catalina.startup.Bootstrap
[root@tomcat ~]# jps -lv
    2018 org.apache.catalina.startup.Bootstrap -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp
    2637 sun.tools.jps.Jps -Dapplication.home=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el8_5.x86_64 -Xms8m
[root@tomcat ~]# jps -lvm
    2018 org.apache.catalina.startup.Bootstrap start -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/local/tomcat/endorsed -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp
    2649 sun.tools.jps.Jps -lvm -Dapplication.home=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.332.b09-1.el8_5.x86_64 -Xms8m

[root@tomcat ~]# jstat -gc 2018
[root@tomcat ~]# jstack 2018
[root@tomcat ~]# jmap 2018

// 图形工具
	jconsole
	jvisualvm

CATALINA_OPTS="$CATALINA_OPTS \
-Dcom.sun.management.jmxremote \									# jmxremote 开启功能
-Dcom.sun.management.jmxremote.port=12345 \							# 指定端口号 12345固定端口 +2个随机端口
-Dcom.sun.management.jmxremote.authenticate=false \					# 是否开启认证功能,一般使用内网访问无需认证
-Dcom.sun.management.jmxremote.ssl=false \							# 是否启用ssl,一般使用内网访问无需ssl
-Djava.rmi.server.hostname=内网IP地址" 								 # 监听的IP,选择内网IP,使用内网访问

Tomcat服务器(192.168.88.88Tomcat目录为/usr/local/tomcat):
[root@tomcat tomcat]# bin/catalina.sh			// 注释行后增加六行
CATALINA_OPTS="$CATALINA_OPTS \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname=192.168.88.88"
[root@tomcat tomcat]# ss -ntulp | grep 12345
	tcp   LISTEN 0      50                      *:12345            *:*    users:(("java",pid=3010,fd=22)) 

开发在Windows找到jconsole或jvisualvm所在的路径,运行后使用连接192.168.88.8812345端口

故障案例

开启自启失败或定时任务重启失败

Tomcat没有创建systemd.service,而是通过在/etc/rc.d/rc.local写入手动启动的命令`Tomcat目录/bin/startup.sh`,开机后Tomcat没有运行。

可能原因:如果JDK不是通过YUM安装的,而是手动安装后自定义PATH,则系统开机或定时任务运行时不会加载自定义的PATH路径,无法检测到JDK,因而无法启动Tomcat
解决方法一:YUM安装JDK
解决方法二:将自定义PATH写入脚本(开机运行的/etc/rc.d/rc.local,或定时任务的自定义脚本),让系统识别JDK后再启动Tomcat

服务器运行时占用大量swap,内存占用较少

服务器运行时占用大量swap,占用物理内存较少

原因:代码问题,需要查看并修改程序代码
临时解决:临时增大swap以免服务器宕机,再通过调整内核参数使系统优先使用物理内存
[root@tomcat ~]# echo 'vm.swappiness = 0' >> /etc/sysctl.conf 	// vm.swappiness是swap亲和性,越大越优先使用swap,越小越优先使用内存
[root@tomcat ~]# sysctl -p

高负载排查

高负载情况的排查命令
1.整体排查,找到出问题的进程PIDps auxtop
2.查看问题进程下的线程负载情况,找到出问题的线程PIDtop -Hp 线程PID
3.将线程的PID转换为十六进制的NID`echo ‘obase=16;线程PID’
4.查看问题进程的详细信息,过滤具体的线程`jstack 进程PID
5.查看jvm的内存使用情况jmap -heap 进程PID
6.导出jvm的内存使用情况jmap -dump:format=b,file=/root/tomcatjvm.bin 进程PID
7.将导出文件给开发人员开发人员通过Windows的mat软件(Eclipse Memory Analyzer Tool)分析
// 高负载排查
// 1.整体排查,找到出问题的进程PID
[root@tomcat ~]# top 或 ps aux		// 假设高负载的是Tomcat604
    ……省略一万字
[root@tomcat ~]# jps				// 如果确定是java的进程也可以通过jps查看PID
    744 Jps
    604 Bootstrap

// 2.查看问题进程下的线程负载情况,找到出问题的线程PID
[root@tomcat ~]# top -Hp 604		// 假设高负载的是线程605
    ……省略一万字
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND  
    604 root      20   0 2937200 250820  18700 S   0.0  12.7   0:00.00 java 
    605 root      20   0 2937200 250820  18700 S  80.0  12.7   0:00.55 java 	
    ……省略一万字

// 3.线程的PID转换为十六进制的NID
[root@tomcat ~]# yum install -y bc
[root@tomcat ~]# echo 'obase=16;605' | bc		// jstack中的线程PID是十六进程的NID
	25D

// 4.查看问题进程的详细信息,过滤具体的线程
[root@tomcat ~]# jstack 604			
    ……省略一万字
    "main" #1 prio=5 os_prio=0 tid=0x00007f59b404d800 nid=0x25d runnable [0x00007f59bb59f000]
       java.lang.Thread.State: RUNNABLE
            at java.net.PlainSocketImpl.socketAccept(Native Method)
            at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
            at java.net.ServerSocket.implAccept(ServerSocket.java:560)
            at java.net.ServerSocket.accept(ServerSocket.java:528)
    ……省略一万字
[root@tomcat ~]# jstack 604| grep -i -A2 25D	// 过滤进程信息中的线程信息
    "main" #1 prio=5 os_prio=0 tid=0x00007f59b404d800 nid=0x25d runnable [0x00007f59bb59f000]
       java.lang.Thread.State: RUNNABLE
            at java.net.PlainSocketImpl.socketAccept(Native Method)

// 5.查看jvm的内存使用情况
[root@tomcat ~]# jmap -heap 604
    Attaching to process ID 604, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.332-b09

    using thread-local object allocation.
    Parallel GC with 2 thread(s)

	Heap Configuration:
    ……省略一万字

	Heap Usage:
    ……省略一万字

	11209 interned Strings occupying 961752 bytes.

// 6.导出jvm的内存使用情况
[root@tomcat ~]# jmap -dump:format=b,file=/root/tomcatjvm.bin 604
    Dumping heap to /root/tomcatjvm.bin ...
    Heap dump file created
[root@tomcat ~]# ll /root/tomcatjvm.bin 
	-rw------- 1 root root 120920576 Oct 26 16:52 /root/tomcatjvm.bin
[root@tomcat ~]# file /root/tomcatjvm.bin
	/root/tomcatjvm.bin: Java HPROF dump, created Thu Oct 26 08:52:57 2023

// 7.将导出文件给开发人员,开发人员通过Windows的mat软件(Eclipse Memory Analyzer Tool)分析

Tomcat优化

安全优化

修改shutdown端口
[root@tomcat tomcat]# vim conf/server.xml
    <Server port="8005" shutdown="SHUTDOWN">	# 修改前
    <Server port="8555" shutdown="dangerous">	# 修改后
修改AJP端口
[root@tomcat tomcat]# vim conf/server.xml		
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />	# 修改前	// 8.5起已经被注释
禁用管理端
// 注释或删除server.xml中关于管理端的配置
[root@tomcat tomcat]# vim conf/server.xml
    <!--
     <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>
    -->
[root@tomcat tomcat]# systemctl restart tomcat.service
// 删除管理端的相关文件
[root@tomcat tomcat]# rm -rf webapps/host-manager
[root@tomcat tomcat]# rm -rf webapps/manager
降权启动(监牢模式)
  • linux中 1-1024是特权端口,只能root管理与运行,因此如果nginx要使用非root启动则需要修改监听端口。
让普通用户启动和运行服务:
1.root关闭tomcat
2.修改tomcat目录的所有者所属组
3.授权用户使用systemctl重启tomcat
4.修改systemctl的运行用户
5.如果不配置34,也可以使用路径启动关闭服务

// 1.root关闭tomcat,根据对应的启动方式关闭
[root@tomcat ~]# systemctl stop tomcat.service
[root@tomcat ~]# /usr/local/tomcat/bin/shutdown.sh
[root@tomcat ~]# ss -ntulp | grep 8080
[root@tomcat ~]# jps
	1426 Jps

// 2.修改tomcat目录的所有者所属组
[root@tomcat ~]# useradd tomcat
[root@tomcat ~]# chown -R tomcat:tomcat /usr/local/tomcat/

// 3.授权用户使用systemctl重启tomcat
[root@tomcat ~]# visudo											// 末尾增加一行
	tomcat  ALL=(ALL)  NOPASSWD:/bin/systemctl restart tomcat

// 4.修改systemctl的运行用户
[root@tomcat ~]# vim /usr/lib/systemd/system/tomcat.service		// 在[Service]内增加一行
	[Service]			
	User=tomcat
[root@tomcat ~]# systemctl daemon-reload 

// 验证
[root@tomcat ~]# su - tomcat
[tomcat@tomcat ~]$ sudo systemctl restart tomcat.service 
[tomcat@tomcat ~]$ ss -ntulp | grep 8080
	tcp   LISTEN 0      100                     *:8080             *:*    users:(("java",pid=1630,fd=52))
[tomcat@tomcat ~]$ jps
    1660 Jps
    1630 Bootstrap
[tomcat@tomcat ~]$ logout
[root@tomcat ~]# systemctl stop tomcat.service
[root@tomcat ~]# ps aux | grep java								// 可以看到tomcat运行tomcat

// 如果不配置3、4,也可以使用路径启动关闭服务
[tomcat@tomcat ~]$ /usr/local/tomcat/bin/startup.sh 
[tomcat@tomcat ~]$ ss -ntulp | grep 8080
	tcp   LISTEN 0      100                     *:8080             *:*    users:(("java",pid=1761,fd=52))
[tomcat@tomcat ~]$ jps
    1761 Bootstrap
    1791 Jps
隐藏版本信息
Nginx不同,Tomcat需要手动修改涉及版本信息的所有网页文件
修改响应头信息
[root@tomcat tomcat]# vim conf/server.xml	
    <Connector port="8080" protocol="HTTP/1.1"		// 修改前
               connectionTimeout="20000"
               redirectPort="8443" />

    <Connector port="8080" protocol="HTTP/1.1"		// 修改后
     	       Server="Nginx/1.20.2" 				// 修改响应头信息
     	       connectionTimeout="20000"
     	       redirectPort="8443" />
[root@tomcat tomcat]# systemctl restart tomcat.service
访问限制
[root@tomcat tomcat]# vim conf/server.xml			// path匹配URI
    <Context path="/admin/" docBase="/home/work/tomcat"
         	 debug="0" reloadable="false" crossContext="true">
        <Valve className="org.apache.catalina.valves.RemoteAddrValve"
               allow="61.148.18.138,61.135.165.*" deny="*.*.*.*"/>
    </Context>
[root@tomcat tomcat]# systemctl restart tomcat.service

性能优化

工作模式(io模型)
模式英文含义
bioblocking iotomcat 7及之前,同步,阻塞,一个线程处理一个请求,缺点:并发量高时,线程数较多,浪费资源。
nionew iotomcat 8及以后,异步,非阻塞,nio1(默认)、 nio2,可以通过少量的线程处理大量的请求
aprApache Portable Runtime应对高并发场景 Tomcat对静态文件的处理性能。Tomcat apr也是在Tomcat上运行高并发应用的首选模式
// 查看效果
[root@tomcat tomcat]# vim logs/catalina.out
	30-Nov-2021 11:17:14.578 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]

[root@tomcat tomcat]# vim conf/server.xml
    <Connector port="8080" protocol="HTTP/1.1"										// 修改前
               connectionTimeout="20000"
               redirectPort="8443" />

    <Connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol"	// 修改后。修改工作模式
               connectionTimeout="20000"
               redirectPort="8443" />
[root@tomcat tomcat]# systemctl restart tomcat.service
禁用DNS逆向解析
[root@tomcat tomcat]# vim conf/server.xml
    <Connector port="8080" protocol="HTTP/1.1"			// 修改前
               connectionTimeout="20000"
               redirectPort="8443" />

    <Connector port="8080" protocol="HTTP/1.1"			// 修改后
               enableLookups="false"					// 禁用DNS逆向解析
               connectionTimeout="20000"
               redirectPort="8443" />
[root@tomcat tomcat]# systemctl restart tomcat.service
开启压缩功能gzip
nginx使用gzip on;

tomcat使用compression;
    compression="on" 					# 开启压缩功能静态文本资源 html js css
    compressionMinSize="2048" 			# 压缩文件,最小2048字节要求(未达2048字节不压缩)
    compressableMimeType="text/html,text/plain,text/css,application/javascript,application/json,application/x-font-ttf,application/x-font-otf" 			# 压缩哪些类型的文件 文本类型 js,css,html

[root@tomcat tomcat]# vim conf/server.xml
    <Connector port="8080" protocol="HTTP/1.1"			// 修改前
               connectionTimeout="20000"
               redirectPort="8443" />

    <Connector port="8080" protocol="HTTP/1.1"			// 修改后
               compression="on"
               compressionMinSize="2048"
               compressableMimeType="text/html,text/plain,text/css,application/javascript,application/json,application/x-font-ttf,application/x-font-otf"
               connectionTimeout="20000"
               redirectPort="8443" />
[root@tomcat tomcat]# systemctl restart tomcat.service

验证:浏览器——》F12——》Network——》Response Headers——》Content-Encoding
线程数量
maxThreads="500" 				# 最大的线程数量 200-400之间
minSpareThreads="10" 			# 空闲时候最小的线程数量
acceptCount="500" 				# 当达到最大线程数量时的队列长度,一般与maxThreads一致。多于maxThreads的在acceptCount排队
acceptorThreadCount="2" 		# 每个线程接受的连接请求数量,一般与cpu核心总数一致或2倍,默认是1

[root@tomcat tomcat]# vim conf/server.xml
    <Connector port="8080" protocol="HTTP/1.1"			// 修改前
               connectionTimeout="20000"
               redirectPort="8443" />

    <Connector port="8080" protocol="HTTP/1.1"			// 修改后
               maxThreads="500" 	
               minSpareThreads="10"			
               acceptCount="500" 	
               acceptorThreadCount="2" 	
               connectionTimeout="20000"
               redirectPort="8443" />
[root@tomcat tomcat]# systemctl restart tomcat.service
jvm内存调整
-Xms # start,初始内存
-Xmx # max,最大内存
官方建议 jvm初始内存大小是物理内存1/64,jvm最大内存大小是物理内存的1/4
实际使用 jvm最大内存大小是初始内存大小的一到两倍,因为有gc垃圾回收,差距太大造成浪费

[root@tomcat tomcat]# vim bin/catalina.sh 			// 增加一行
	JAVA_OPTS='-Xms1024m -Xmx1024m -Xloggc:/var/log/tomcat_gc.log'

end

  • 16
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值