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/downloadTomcat https://tomcat.apache.org/注意:Tomcat/conf/startup.sh 配置文件错误时不会报错。Tomcat/conf/shutdown.sh 重复关闭时会报错。
// 安装Tomcat
Tomcat服务器(192.168.88.88,Tomcat目录为/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.88,Tomcat目录为/usr/local/tomcat):
浏览器访问 http://192.168.88.88:8080
可以通过Server Status、Manager App、Host Manager管理Tomcat
Tomcat 8.5以后,默认只能本地环回地址访问127.0.0.1
// 开启功能并设置用户密码
[root@tomcat tomcat]# vim conf/tomcat-users.xml // 管理网页配置文件
39
40
41
42
[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
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 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相关的配置 [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 # 去除注释之后的有效内容 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" /> connectionTimeout="20000" redirectPort="8443" /> resourceName="UserDatabase"/> unpackWARs="true" autoDeploy="true"> prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> 8005是shutdown端口:`telnet 127.0.0.1 8005`后输入SHUTDOWN 8080是HTTP端口 8443是HTTPS端口,默认关闭 8009是AJP端口,用于tomcat和apache的交互,8.5版本后默认关闭 Tomcat处理用户请求的流程: 用户发出请求——》请求达到Tomcat——》 日志格式 访问日志内容的格式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 虚拟主机 name:虚拟主机名称,也是域名。appBase:网页目录。unpackWARs:是否自动解WAR包,默认为true。autoDeploy:是否自动部署,默认为true。 注意:如果配置了[降权启动](# 降权启动(监牢模式)),那么要修改数据的所有者所属组。 // 虚拟主机 Tomcat服务器(192.168.88.88,Tomcat目录为/usr/local/tomcat): // 配置 [root@tomcat tomcat]# cp server.xml{.default,} [root@tomcat tomcat]# vim conf/server.xml // 在 unpackWARs="true" autoDeploy="true"> prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> unpackWARs="true" autoDeploy="true"> prefix="test_access_log" suffix=".log" pattern="%h %l %u %t "%r" %s %b" /> unpackWARs="true" autoDeploy="true"> prefix="test_access_log" suffix=".log" pattern="%h %l %u %t "%r" %s %b" /> [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 访问路径 注意:如果配置了[降权启动](# 降权启动(监牢模式)),那么要修改数据的所有者所属组。 不定义appBase,指向 Tomcat/webappsappBase="",指向 Tomcat/appBase="相对路径",指向 Tomcat/相对路径appBase="绝对路径",指向 绝对路径/ 属性 path(精确匹配,支持*和?)的使用:只有当客户端访问的URI匹配path时, path的值可以为空"",也可以为"/路径"(必须以/开头且不能以/结尾) - 当path为空""时,可以不定义docBase。此时,只有匹配不含目录的URI, 当path不为空"/路径"时,就必须定义docBase。此时,只有URI匹配"/路径"时, path="/字符串A"时,字符串匹配URI。 // 访问路径 appBase的使用: - 不定义appBase,指向 Tomcat/webapps - appBase="",指向 Tomcat/ - appBase="相对路径",指向 Tomcat/相对路径 - appBase="绝对路径",指向 绝对路径 path(精确匹配,支持*和?)的使用:只有当客户端访问的URI匹配path时, - 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, - 当path不为空"/路径"时,就必须定义docBase。此时,只有URI匹配"/路径"时, - 定义了appBase,就必须定义path。 Tomcat服务器(192.168.88.88,Tomcat目录为/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} unpackWARs="true" autoDeploy="true"> prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> [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则 [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时 // 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的子选项,指定存储密钥对的密钥库文件 注意:一个密钥库文件中可以有多个密钥对。 在配置Tomcat的SSL时, 必须:关键字keystoreFile指定密钥库文件,关键字keystorePass指定密钥库文件密码 选用:关键字keyAlias指定密钥库文件中的密钥对(省略默认为第一个密钥对),关键字keyPass指定密钥对密码(省略默认同keystorePass) Tomcat服务器(192.168.88.88,Tomcat目录为/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 (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 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.88,Tomcat目录为/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.88,Tomcat目录为/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: tomcat_8081/conf/server.xml: tomcat_8082/conf/server.xml: tomcat_8082/conf/server.xml: [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.88,Tomcat目录为/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.88,Tomcat目录为/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.88的12345端口 故障案例 开启自启失败或定时任务重启失败 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 aux或top2.查看问题进程下的线程负载情况,找到出问题的线程PIDtop -Hp 线程PID3.将线程的PID转换为十六进制的NID`echo ‘obase=16;线程PID’4.查看问题进程的详细信息,过滤具体的线程`jstack 进程PID5.查看jvm的内存使用情况jmap -heap 进程PID6.导出jvm的内存使用情况jmap -dump:format=b,file=/root/tomcatjvm.bin 进程PID7.将导出文件给开发人员开发人员通过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 修改AJP端口 [root@tomcat tomcat]# vim conf/server.xml 禁用管理端 // 注释或删除server.xml中关于管理端的配置 [root@tomcat tomcat]# vim conf/server.xml [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.如果不配置3、4,也可以使用路径启动关闭服务 // 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 connectionTimeout="20000" redirectPort="8443" /> 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 debug="0" reloadable="false" crossContext="true"> allow="61.148.18.138,61.135.165.*" deny="*.*.*.*"/> [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 connectionTimeout="20000" redirectPort="8443" /> connectionTimeout="20000" redirectPort="8443" /> [root@tomcat tomcat]# systemctl restart tomcat.service 禁用DNS逆向解析 [root@tomcat tomcat]# vim conf/server.xml connectionTimeout="20000" redirectPort="8443" /> 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 connectionTimeout="20000" redirectPort="8443" /> 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 connectionTimeout="20000" redirectPort="8443" /> 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 精彩内容
发表评论