企业级应用Tomcat实战 1. Tomcat简介 1.1 什么是Tomcat Apache Tomcat 是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。Tomcat服务器是一个免费的开放源代码的Web应用服务器 ,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。
Tomcat的核心特性 :
Servlet容器 :独立的Servlet容器是Tomcat的默认模式
JSP支持 :支持JavaServer Pages(JSP)技术
轻量级 :相比WebLogic、WebSphere等重量级应用服务器更轻量
开源免费 :Apache开源许可证,完全免费
跨平台 :支持Windows、Linux、Unix等多种操作系统
1.2 Tomcat与其他Web服务器对比 1.2.1 Tomcat vs Nginx/Apache
特性
Tomcat
Nginx/Apache
主要功能
Servlet/JSP容器
静态Web服务器
处理静态HTML
能力较弱
性能优秀
处理动态内容
优秀(Java应用)
需要配合PHP/Python等
资源消耗
较高(Java应用)
较低
适用场景
Java Web应用
静态网站、反向代理
典型架构 :
1 用户请求 → Nginx(反向代理、静态资源) → Tomcat(动态内容)
1.2.2 Tomcat vs PHP软件栈 PHP软件栈 :
Web服务器 :Nginx/Apache
应用服务器 :PHP-FPM
数据库 :MySQL/MariaDB
Java软件栈 :
Web服务器 :Nginx/Apache(可选)
应用服务器 :Tomcat/Jetty
数据库 :MySQL/Oracle/PostgreSQL
主要区别 :
语言 :PHP vs Java
部署方式 :PHP脚本直接执行 vs Java编译后运行
性能 :PHP轻量快速 vs Java需要JVM
生态 :PHP框架(Laravel、ThinkPHP)vs Java框架(Spring、Struts)
1.3 Tomcat版本 当前主流版本 :
Tomcat 9.x :最新稳定版,支持Servlet 4.0、JSP 2.3
Tomcat 8.x :广泛使用,支持Servlet 3.1、JSP 2.3
Tomcat 7.x :较老版本,支持Servlet 3.0、JSP 2.2
其他Java容器 :
Resin :商业/开源Java应用服务器
WebLogic :Oracle商业应用服务器
WebSphere :IBM商业应用服务器
Jetty :轻量级嵌入式Servlet容器
1.4 Tomcat在企业中的应用 典型应用场景 :
企业级Web应用 :ERP、CRM、OA系统
电商平台 :在线购物、支付系统
金融系统 :银行、证券、保险业务系统
政府系统 :电子政务、公共服务平台
2. Tomcat安装 2.1 软件准备 2.1.1 下载地址 JDK下载 :
Tomcat下载 :
系统要求 :
操作系统 :Linux(CentOS 7+、Ubuntu 18+)、Windows Server
内存 :最低2GB,推荐4GB+
磁盘 :至少1GB可用空间
Java版本 :JDK 8或更高版本
2.1.2 软件版本选择 JDK版本选择 :
JDK 8 :LTS版本,稳定可靠,推荐生产环境
JDK 11 :LTS版本,性能更好
JDK 17 :最新LTS版本
Tomcat版本选择 :
Tomcat 8.5 :稳定,广泛使用
Tomcat 9.x :新特性,性能优化
2.2 部署Java环境 2.2.1 安装JDK 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 cd /application/tools/wget https://download.oracle.com/java/8/latest/jdk-8uXXX-linux-x64.tar.gz tar xf jdk-8u60-linux-x64.tar.gz -C /application/ ln -s /application/jdk1.8.0_60 /application/jdkcat >> /etc/profile << 'EOF' export JAVA_HOME=/application/jdkexport PATH=$JAVA_HOME /bin:$JAVA_HOME /jre/bin:$PATH export CLASSPATH=.:$CLASSPATH :$JAVA_HOME /lib:$JAVA_HOME /jre/lib:$JAVA_HOME /lib/tools.jarEOF source /etc/profilejava -version
验证输出 :
1 2 3 java version "1.8.0_60" Java(TM) SE Runtime Environment (build 1.8.0_60-b27) Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
2.2.2 使用YUM安装JDK(可选) 1 2 3 4 5 yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel apt-get install -y openjdk-8-jdk
2.3 安装Tomcat 2.3.1 安装步骤 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 cd /application/tools/wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.27/bin/apache-tomcat-8.0.27.tar.gz tar xf apache-tomcat-8.0.27.tar.gz -C /application/ ln -s /application/apache-tomcat-8.0.27 /application/tomcatecho 'export TOMCAT_HOME=/application/tomcat' >> /etc/profilesource /etc/profilechown -R root.root /application/jdk/ /application/tomcat/tail -4 /etc/profile
环境变量配置 :
1 2 3 4 export JAVA_HOME=/application/jdkexport PATH=$JAVA_HOME /bin:$JAVA_HOME /jre/bin:$PATH export CLASSPATH=.:$CLASSPATH :$JAVA_HOME /lib:$JAVA_HOME /jre/lib:$JAVA_HOME /lib/tools.jarexport TOMCAT_HOME=/application/tomcat
2.3.2 创建Tomcat用户(推荐) 1 2 3 4 5 6 7 8 useradd -M -s /sbin/nologin tomcat chown -R tomcat.tomcat /application/tomcat/chmod +x /application/tomcat/bin/*.sh
2.4 Tomcat目录介绍 2.4.1 目录结构 1 2 3 4 5 6 7 8 9 10 [root@tomcat ~] [root@tomcat tomcat] . ├── bin ├── conf ├── lib ├── logs ├── temp ├── webapps └── work
2.4.2 目录详解 bin目录 :
startup.sh:启动脚本
shutdown.sh:关闭脚本
catalina.sh:核心启动脚本
version.sh:版本查看脚本
conf目录 :
server.xml:主配置文件
web.xml:Web应用默认配置
tomcat-users.xml:用户管理配置
context.xml:上下文配置
logging.properties:日志配置
webapps目录 :
ROOT:默认网站根目录
docs:Tomcat帮助文档
examples:Web应用示例
host-manager:主机管理
manager:应用管理
logs目录 :
catalina.out:标准输出日志
catalina.YYYY-MM-DD.log:按日期分类的日志
localhost.YYYY-MM-DD.log:本地主机日志
localhost_access_log.YYYY-MM-DD.txt:访问日志
2.5 启动Tomcat 2.5.1 启动方式 1 2 3 4 5 6 7 8 /application/tomcat/bin/startup.sh /application/tomcat/bin/catalina.sh start systemctl start tomcat
启动输出 :
1 2 3 4 5 6 Using CATALINA_BASE: /application/tomcat Using CATALINA_HOME: /application/tomcat Using CATALINA_TMPDIR: /application/tomcat/temp Using JRE_HOME: /application/jdk Using CLASSPATH: /application/tomcat/bin/bootstrap.jar:/application/tomcat/bin/tomcat-juli.jar Tomcat started.
2.5.2 验证启动 1 2 3 4 5 6 7 8 9 10 netstat -tunlp | grep java ss -tunlp | grep java ps -ef | grep [j]ava tail -f /application/tomcat/logs/catalina.out
端口说明 :
8080 :HTTP连接器端口
8009 :AJP连接器端口(用于与Apache集成)
8005 :Shutdown端口
2.5.3 关闭Tomcat 1 2 3 4 5 6 7 8 9 10 /application/tomcat/bin/shutdown.sh /application/tomcat/bin/catalina.sh stop killall java pkill -f tomcat
2.6 访问网站 2.6.1 访问Tomcat默认页面 访问地址 :
http://服务器IP:8080/
http://localhost:8080/
默认页面内容 :
2.6.2 防火墙配置 1 2 3 4 5 6 7 firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --reload iptables -A INPUT -p tcp --dport 8080 -j ACCEPT service iptables save
2.7 Tomcat日志 2.7.1 日志文件说明 1 2 3 4 5 6 7 [root@tomcat logs] -rw-r--r-- 1 root root 10K Jan 26 06:10 catalina.2016-01-26.log -rw-r--r-- 1 root root 50K Jan 26 06:10 catalina.out -rw-r--r-- 1 root root 1.2K Jan 26 06:10 host-manager.2016-01-26.log -rw-r--r-- 1 root root 2.1K Jan 26 06:10 localhost.2016-01-26.log -rw-r--r-- 1 root root 5.3K Jan 26 06:10 localhost_access_log.2016-01-26.txt -rw-r--r-- 1 root root 1.5K Jan 26 06:10 manager.2016-01-26.log
日志文件说明 :
catalina.out:标准输出和错误输出
catalina.YYYY-MM-DD.log:按日期分类的日志
localhost.YYYY-MM-DD.log:本地主机日志
localhost_access_log.YYYY-MM-DD.txt:访问日志
manager.YYYY-MM-DD.log:管理应用日志
host-manager.YYYY-MM-DD.log:主机管理日志
2.7.2 查看实时日志 1 2 3 4 5 6 7 8 9 10 11 tail -f /application/tomcat/logs/catalina.outtail -n 100 /application/tomcat/logs/catalina.outgrep -i error /application/tomcat/logs/catalina.out tail -f /application/tomcat/logs/localhost_access_log.$(date +%Y-%m-%d).txt
2.7.3 日志轮转配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 cat > /etc/logrotate.d/tomcat << 'EOF' /application/tomcat/logs/*.log { daily rotate 30 compress delaycompress missingok notifempty create 0644 tomcat tomcat sharedscripts postrotate /application/tomcat/bin/shutdown.sh > /dev/null 2>&1 || true /application/tomcat/bin/startup.sh > /dev/null 2>&1 || true endscript } EOF
3. Tomcat配置文件 3.1 Tomcat配置文件 3.1.1 配置文件列表 1 2 3 4 5 6 7 8 9 10 11 [root@tomcat conf] total 216K drwxr-xr-x 3 root root 4.0K Jan 26 06:10 Catalina -rw------- 1 root root 13K Sep 28 16:19 catalina.policy -rw------- 1 root root 7.0K Sep 28 16:19 catalina.properties -rw------- 1 root root 1.6K Sep 28 16:19 context.xml -rw------- 1 root root 3.4K Sep 28 16:19 logging.properties -rw------- 1 root root 6.4K Sep 28 16:19 server.xml -rw------- 1 root root 1.8K Sep 28 16:19 tomcat-users.xml -rw------- 1 root root 1.9K Sep 28 16:19 tomcat-users.xsd -rw------- 1 root root 164K Sep 28 16:19 web.xml
配置文件说明 :
server.xml:Tomcat主配置文件,核心配置
web.xml:Web应用默认配置
tomcat-users.xml:用户管理配置
context.xml:上下文配置
logging.properties:日志配置
catalina.policy:安全策略文件
3.2 Tomcat管理 3.2.1 配置管理用户 Tomcat管理功能 :
Manager App :应用管理
Host Manager :主机管理
配置步骤 :
1 2 vim /application/tomcat/conf/tomcat-users.xml
配置内容 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?xml version='1.0' encoding='utf-8'?> <tomcat-users > <role rolename ="manager-gui" /> <role rolename ="manager-script" /> <role rolename ="manager-jmx" /> <role rolename ="manager-status" /> <role rolename ="admin-gui" /> <role rolename ="admin-script" /> <user username ="tomcat" password ="tomcat" roles ="manager-gui,admin-gui" /> </tomcat-users >
角色说明 :
manager-gui:Web界面管理权限
manager-script:脚本管理权限
manager-jmx:JMX管理权限
manager-status:状态查看权限
admin-gui:主机管理界面权限
admin-script:主机管理脚本权限
3.2.2 访问管理界面 访问地址 :
Manager App:http://服务器IP:8080/manager/html
Host Manager:http://服务器IP:8080/host-manager/html
安全建议 :
生产环境建议禁用管理功能
如需使用,限制访问IP
使用强密码
启用HTTPS
3.3 Tomcat主配置文件Server.xml详解 3.3.1 server.xml组件类别 组件层次结构 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <Server > <Service > <Connector /> <Engine > <Host > <Context > </Context > <Valve /> <Logger /> </Host > <Realm /> </Engine > </Service > </Server >
组件分类 :
顶级组件 :位于整个配置的顶层,如<Server>
容器类组件 :可以包含其它组件的组件,如<Service>、<Engine>、<Host>、<Context>
连接器组件 :连接用户请求至Tomcat,如<Connector>
被嵌套类组件 :位于一个容器当中,不能包含其他组件,如<Valve>、<Logger>、<Realm>
3.3.2 组件详解 Server组件 :
表示一个运行于JVM中的Tomcat实例
一个Server可以包含多个Service
Service组件 :
将Connector关联至Engine
一个Service内部可以有多个Connector,但只能有一个Engine
一般情况下一个Server内部只有一个Service
Engine组件 :
核心容器组件,Catalina引擎
负责通过Connector接收用户请求,并处理请求
将请求转至对应的虚拟主机Host
Host组件 :
类似于HTTPd中的虚拟主机
支持基于FQDN的虚拟主机
可以配置多个Host
Context组件 :
定义一个应用程序,是最内层的容器类组件
配置Context的主要目的是指定对应的Webapp的根目录
类似于HTTPd的alias
Connector组件 :
接收用户请求
类似于HTTPd的listen配置监听端口
支持HTTP和AJP协议
Valve组件 :
阀门,拦截请求并在将其转至对应的Webapp前进行某种处理操作
可以用于任何容器中
例如:记录日志(AccessLogValve)、基于IP做访问控制(RemoteAddrFilterValve)
Logger组件 :
日志记录器,用于记录组件内部的状态信息
可以用于除Context外的任何容器中
Realm组件 :
可以用于任意容器类的组件中
关联一个用户认证库,实现认证和授权
类型:UserDatabaseRealm、MemoryRealm、JDBCRealm
3.3.3 配置文件注释详解 完整server.xml配置示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 <?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" enableLookups ="false" acceptCount ="100" /> <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" xmlValidation ="false" xmlNamespaceAware ="false" > <Context path ="" docBase ="" debug ="0" reloadable ="false" /> <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 >
4. Web站点部署 4.1 使用WAR包部署Web站点 4.1.1 WAR包部署方式 方式1:直接部署WAR包
1 2 3 4 5 6 7 8 9 10 11 cd /application/tomcat/webapps/rz /application/tomcat/bin/shutdown.sh /application/tomcat/bin/startup.sh ls -lh webapps/
方式2:使用Manager部署
4.1.2 访问部署的应用 访问地址 :
http://服务器IP:8080/memtest/meminfo.jsp
http://服务器IP:8080/memtest/(如果有index页面)
WAR包说明 :
WAR(Web Application Archive)是Java Web应用的打包格式
类似于JAR文件,但用于Web应用
包含完整的Web应用结构
4.2 自定义默认网站目录 4.2.1 方法一:使用ROOT目录 1 2 3 4 5 6 cp /application/tomcat/webapps/memtest/meminfo.jsp \ /application/tomcat/webapps/ROOT/
4.2.2 方法二:修改Context配置 1 2 vim /application/tomcat/conf/server.xml
配置内容 :
1 2 3 4 5 6 7 8 9 <Host name ="localhost" appBase ="webapps" unpackWARs ="true" autoDeploy ="true" > <Context path ="" docBase ="/application/tomcat/webapps/memtest" debug ="0" reloadable ="false" crossContext ="true" /> </Host >
参数说明 :
path="":URL路径前缀,空表示根路径
docBase:应用程序路径
reloadable:是否自动重新加载
crossContext:是否允许跨上下文访问
重启Tomcat :
1 2 /application/tomcat/bin/shutdown.sh /application/tomcat/bin/startup.sh
访问地址 :
http://服务器IP:8080/meminfo.jsp
4.2.3 方法三:使用独立Context文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 mkdir -p /application/tomcat/conf/Catalina/localhost/cat > /application/tomcat/conf/Catalina/localhost/ROOT.xml << 'EOF' <?xml version="1.0" encoding="UTF-8" ?> <Context path="" docBase="/application/tomcat/webapps/memtest" reloadable="false" /> EOF /application/tomcat/bin/shutdown.sh /application/tomcat/bin/startup.sh
优势 :
不需要修改server.xml
支持热部署
配置更灵活
5. Tomcat多实例及集群架构 5.1 Tomcat多实例 5.1.1 多实例概述 多实例的优势 :
资源隔离 :不同应用互不影响
独立配置 :每个实例可以独立配置
负载分担 :可以分担单个实例的压力
故障隔离 :一个实例故障不影响其他实例
5.1.2 复制Tomcat目录 1 2 3 4 5 6 7 8 cd /application/cp -a apache-tomcat-8.0.27 tomcat8_1cp -a apache-tomcat-8.0.27 tomcat8_2mkdir -p /data/www/www/ROOTcp /application/tomcat/webapps/memtest/meminfo.jsp /data/www/www/ROOT/
5.1.3 修改配置文件 修改实例1配置 :
1 2 3 sed -i '22s#8005#8011#;69s#8080#8081#;123s#appBase=".*"# appBase="/data/www/www"#' \ /application/tomcat8_1/conf/server.xml
修改实例2配置 :
1 2 3 sed -i '22s#8005#8012#;69s#8080#8082#;123s#appBase=".*"# appBase="/data/www/www"#' \ /application/tomcat8_2/conf/server.xml
配置文件修改说明 :
Shutdown端口 :8005 → 8011/8012(避免冲突)
HTTP端口 :8080 → 8081/8082(避免冲突)
appBase :指向共享的Web应用目录
验证配置 :
1 2 3 diff /application/tomcat/conf/server.xml /application/tomcat8_1/conf/server.xml diff /application/tomcat/conf/server.xml /application/tomcat8_2/conf/server.xml
5.1.4 启动多实例 1 2 3 4 5 6 7 8 for i in {1..2}; do /application/tomcat8_$i /bin/startup.sh done netstat -tunlp | grep java ps -ef | grep [j]ava
访问验证 :
http://服务器IP:8081/meminfo.jsp
http://服务器IP:8082/meminfo.jsp
5.1.5 多实例启动脚本 创建启动脚本 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 cat > /etc/init.d/tomcat << 'EOF' . /etc/rc.d/init.d/functions TOMCAT_PATH=/application/tomcat8_1 TOMCAT_USER=tomcat usage (){ echo "Usage: $0 [start|stop|restart|status] [instance_number]" echo "Example: $0 start 1" } status_tomcat (){ local instance=$1 local path=/application/tomcat8_${instance} STATUS=$(ps aux | grep java | grep "catalina.base=$path " | grep -v 'grep' | awk '{print $2}' ) if [ -z "$STATUS " ]; then echo "Tomcat instance $instance is stopped" else echo "Tomcat instance $instance (pid $STATUS ) is running..." fi } start_tomcat (){ local instance=$1 local path=/application/tomcat8_${instance} if [ ! -d "$path " ]; then echo "Error: Tomcat instance $instance not found" exit 1 fi su - $TOMCAT_USER -c "$path /bin/startup.sh" >/dev/null 2>&1 sleep 2 if status_tomcat $instance | grep -q "running" ; then action "Tomcat instance $instance is starting" /bin/true ps aux | grep java | grep "catalina.base=$path " | grep -v 'grep' | awk '{print $2}' > $path /logs/tomcat.pid else action "Tomcat instance $instance is starting" /bin/false fi } stop_tomcat (){ local instance=$1 local path=/application/tomcat8_${instance} if [ -e "$path /logs/tomcat.pid" ]; then TPID=$(cat $path /logs/tomcat.pid) kill $TPID 2>/dev/null sleep 5 TSTAT=$(ps aux | grep java | grep "catalina.base=$path " | grep -v 'grep' | awk '{print $2}' ) if [ -z "$TSTAT " ]; then action "Tomcat instance $instance is stopping" /bin/true rm -f $path /logs/tomcat.pid else kill -9 $TSTAT 2>/dev/null action "Tomcat instance $instance is stopping" /bin/false rm -f $path /logs/tomcat.pid fi rm -rf $path /temp/* rm -rf $path /work/* else action "Tomcat instance $instance is stopped" /bin/false exit 1 fi } main (){ local action=$1 local instance=${2:-1} case $action in status) status_tomcat $instance ;; start) start_tomcat $instance ;; stop) stop_tomcat $instance ;; restart) stop_tomcat $instance && start_tomcat $instance ;; *) usage;; esac } main $@ EOF chmod +x /etc/init.d/tomcat/etc/init.d/tomcat start 1 /etc/init.d/tomcat start 2 /etc/init.d/tomcat status 1 /etc/init.d/tomcat stop 1
5.2 Tomcat集群 5.2.1 Nginx + Tomcat集群架构 架构图 :
1 2 3 4 5 6 7 用户请求 ↓ Nginx (负载均衡) ↓ ├──→ Tomcat实例1 (8081) ├──→ Tomcat实例2 (8082) └──→ Tomcat实例N (808N)
5.2.2 Nginx配置 1 2 vim /application/nginx/conf/nginx.conf
配置内容 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 upstream web_pools { server 127.0.0.1:8081 weight=1 max_fails=2 fail_timeout=30s ; server 127.0.0.1:8082 weight=1 max_fails=2 fail_timeout=30s ; } server { listen 80 ; server_name localhost; access_log logs/tomcat_access.log; error_log logs/tomcat_error.log; location / { root html; index index.jsp index.html index.htm; proxy_pass http://web_pools; proxy_set_header Host $host ; proxy_set_header X-Real-IP $remote_addr ; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ; proxy_set_header X-Forwarded-Proto $scheme ; proxy_connect_timeout 60s ; proxy_send_timeout 60s ; proxy_read_timeout 60s ; proxy_buffering on ; proxy_buffer_size 4k ; proxy_buffers 8 4k ; } location /nginx_status { stub_status on ; access_log off ; allow 127.0.0.1 ; deny all; } }
测试配置 :
1 2 3 4 5 /application/nginx/sbin/nginx -t /application/nginx/sbin/nginx -s reload
访问验证 :
http://服务器IP/meminfo.jsp
多次刷新,查看是否负载均衡
5.2.3 会话保持配置 方式1:使用ip_hash(Nginx)
1 2 3 4 5 upstream web_pools { ip_hash; server 127.0.0.1:8081 ; server 127.0.0.1:8082 ; }
方式2:使用Redis共享Session
1 2 3 4 5 6 7 8 9 10 11 12 <Context > <Manager className ="org.apache.catalina.session.PersistentManager" maxIdleSwap ="30" minIdleSwap ="10" > <Store className ="org.apache.catalina.session.RedisStore" host ="redis-server" port ="6379" database ="0" password ="" /> </Manager > </Context >
6. Tomcat监控 6.1 进程监控 6.1.1 基础监控命令 1 2 3 4 5 6 7 8 9 10 ps -ef | grep [j]ava netstat -tunlp | grep java ss -tunlp | grep java top -p $(pgrep -f tomcat) htop -p $(pgrep -f tomcat)
6.1.2 监控脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 cat > /usr/local/bin/tomcat_monitor.sh << 'EOF' TOMCAT_HOME=/application/tomcat TOMCAT_PORT=8080 check_tomcat (){ PID=$(ps aux | grep java | grep "catalina.base=$TOMCAT_HOME " | grep -v grep | awk '{print $2}' ) if [ -z "$PID " ]; then echo "ERROR: Tomcat process not found" return 1 fi PORT_STATUS=$(netstat -tunlp | grep ":$TOMCAT_PORT " | wc -l) if [ "$PORT_STATUS " -eq 0 ]; then echo "ERROR: Tomcat port $TOMCAT_PORT not listening" return 1 fi HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$TOMCAT_PORT / 2>/dev/null) if [ "$HTTP_STATUS " != "200" ]; then echo "WARNING: Tomcat HTTP response code: $HTTP_STATUS " return 1 fi echo "OK: Tomcat is running (PID: $PID , Port: $TOMCAT_PORT )" return 0 } check_tomcat EOF chmod +x /usr/local/bin/tomcat_monitor.sh
6.2 性能监控 6.2.1 JVM监控 1 2 3 4 5 6 7 8 jstat -gcutil $(pgrep -f tomcat) 1000 jmap -heap $(pgrep -f tomcat) jmap -dump:format=b,file=/tmp/tomcat_heap.hprof $(pgrep -f tomcat)
6.2.2 使用JMX监控 启用JMX :
1 2 vim /application/tomcat/bin/catalina.sh
添加JMX配置 :
1 2 3 4 5 6 JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote \ -Dcom.sun.management.jmxremote.port=9999 \ -Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.ssl=false \ -Djava.rmi.server.hostname=服务器IP"
使用JConsole连接 :
启动JConsole:jconsole
连接:服务器IP:9999
6.3 日志监控 6.3.1 错误日志监控 1 2 3 4 5 6 7 8 tail -f /application/tomcat/logs/catalina.out | grep -i errorgrep -i error /application/tomcat/logs/catalina.out | wc -l grep -i error /application/tomcat/logs/catalina.out | tail -20
6.3.2 访问日志分析 1 2 3 4 5 6 7 awk '{print $1}' /application/tomcat/logs/localhost_access_log.*.txt | sort | uniq -c | sort -rn | head -10 awk '{print $9}' /application/tomcat/logs/localhost_access_log.*.txt | sort | uniq -c | sort -rn
6.4 企业案例:CPU占用高问题解决 6.4.1 问题现象 生产环境下Tomcat服务器,运行一段时间后出现CPU占用很高的问题,负载一天比一天高。
6.4.2 排查步骤 步骤1:查看进程CPU使用情况
1 2 3 top -p $(pgrep -f tomcat) ps aux | grep java | sort -k3 -rn | head -5
步骤2:生成线程转储
1 2 3 4 5 jstack $(pgrep -f tomcat) > /tmp/tomcat_threads.txt cat /tmp/tomcat_threads.txt | grep "java.lang.Thread.State" | sort | uniq -c
步骤3:分析堆内存
1 2 3 4 5 6 jmap -dump:format=b,file=/tmp/tomcat_heap.hprof $(pgrep -f tomcat) jhat /tmp/tomcat_heap.hprof
步骤4:查看GC情况
1 2 3 4 jstat -gcutil $(pgrep -f tomcat) 1000 10
6.4.3 常见原因和解决方案 原因1:内存泄漏
1 2 3 JAVA_OPTS="$JAVA_OPTS -Xms2g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m"
原因2:线程死锁
1 2 jstack $(pgrep -f tomcat) | grep -A 10 "deadlock"
原因3:频繁GC
1 2 JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
原因4:代码性能问题
7. Tomcat安全优化和性能优化 7.1 安全优化 7.1.1 降权启动 1 2 3 4 5 6 7 8 useradd -M -s /sbin/nologin tomcat chown -R tomcat.tomcat /application/tomcat/su - tomcat -c "/application/tomcat/bin/startup.sh"
7.1.2 Telnet管理端口保护 1 2 3 vim /application/tomcat/conf/server.xml
配置示例 :
1 <Server port ="8456" shutdown ="ComplexShutdownPassword123!" >
防火墙限制 :
1 2 3 iptables -A INPUT -p tcp --dport 8456 -s 127.0.0.1 -j ACCEPT iptables -A INPUT -p tcp --dport 8456 -j DROP
7.1.3 AJP连接端口保护 1 2 3 4 5 6 7 8 vim /application/tomcat/conf/server.xml <Connector port="8009" protocol="AJP/1.3" address="127.0.0.1" redirectPort="8443" />
7.1.4 禁用管理端 1 2 3 4 5 6 mv /application/tomcat/webapps/manager /application/tomcat/webapps/manager.bakmv /application/tomcat/webapps/host-manager /application/tomcat/webapps/host-manager.bakvim /application/tomcat/webapps/manager/META-INF/context.xml
限制IP配置 :
1 2 3 4 <Context antiResourceLocking ="false" privileged ="true" > <Valve className ="org.apache.catalina.valves.RemoteAddrValve" allow ="192.168.1.0/24|10.0.0.0/8" /> </Context >
7.1.5 其他安全措施 删除示例应用 :
1 2 rm -rf /application/tomcat/webapps/examplesrm -rf /application/tomcat/webapps/docs
隐藏版本信息 :
1 2 vim /application/tomcat/conf/server.xml
1 2 3 4 <Server port ="8005" shutdown ="SHUTDOWN" > <Listener className ="org.apache.catalina.core.AprLifecycleListener" SSLEngine ="on" /> </Server >
启用HTTPS :
1 2 3 4 5 6 7 8 9 keytool -genkey -alias tomcat -keyalg RSA -keystore /application/tomcat/conf/tomcat.keystore <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" keystoreFile="/application/tomcat/conf/tomcat.keystore" keystorePass="changeit" clientAuth="false" sslProtocol="TLS" />
7.2 性能优化 7.2.1 屏蔽DNS查询 1 2 3 4 <Connector port ="8080" protocol ="HTTP/1.1" connectionTimeout ="20000" enableLookups ="false" <!-- 禁用DNS查询 -- > redirectPort="8443" />
说明 :
enableLookups="false":禁用DNS查询,提高性能
如果不需要获取客户端主机名,建议设置为false
7.2.2 JVM调优 优化catalina.sh :
1 vim /application/tomcat/bin/catalina.sh
添加JVM参数 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 JAVA_OPTS="-Djava.awt.headless=true \ -Dfile.encoding=UTF-8 \ -server \ -Xms1024m \ -Xmx1024m \ -XX:NewSize=512m \ -XX:MaxNewSize=512m \ -XX:MetaspaceSize=256m \ -XX:MaxMetaspaceSize=256m \ -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 \ -XX:+DisableExplicitGC \ -XX:+HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath=/application/tomcat/logs/heap_dump.hprof"
JVM参数说明 :
参数
说明
推荐值
-server
服务器模式,性能更好
必须
-Xms
初始堆内存
物理内存的1/4-1/2
-Xmx
最大堆内存
物理内存的1/2
-XX:NewSize
新生代初始大小
Xmx的1/3-1/4
-XX:MaxNewSize
新生代最大大小
Xmx的1/3-1/4
-XX:MetaspaceSize
元空间初始大小
256m
-XX:MaxMetaspaceSize
元空间最大大小
512m
-XX:+UseG1GC
使用G1垃圾收集器
推荐
-XX:MaxGCPauseMillis
最大GC暂停时间
200ms
GC调优建议 :
小堆内存(<4GB) :使用Parallel GC
大堆内存(>4GB) :使用G1 GC
低延迟要求 :使用ZGC或Shenandoah GC(JDK 11+)
7.2.3 连接器优化 1 2 3 4 5 6 7 8 9 10 11 <Connector port ="8080" protocol ="HTTP/1.1" connectionTimeout ="20000" maxThreads ="1000" minSpareThreads ="100" maxSpareThreads ="500" acceptCount ="1000" enableLookups ="false" compression ="on" compressionMinSize ="2048" compressableMimeType ="text/html,text/xml,text/javascript,text/css,text/plain" redirectPort ="8443" />
参数说明 :
参数
说明
推荐值
maxThreads
最大线程数
1000-2000
minSpareThreads
最小空闲线程数
100-200
maxSpareThreads
最大空闲线程数
500-1000
acceptCount
等待队列长度
1000
compression
启用压缩
on
compressionMinSize
压缩最小大小
2048
7.2.4 状态管理之解决403 问题 :访问Manager App和Host Manager显示403
原因 :Tomcat 7+版本默认限制访问IP
解决方案 :
1 2 vim /application/tomcat/webapps/manager/META-INF/context.xml
修改前 :
1 2 3 4 <Context antiResourceLocking ="false" privileged ="true" > <Valve className ="org.apache.catalina.valves.RemoteAddrValve" allow ="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> </Context >
修改后 (允许所有IP):
1 2 3 4 <Context antiResourceLocking ="false" privileged ="true" > <Valve className ="org.apache.catalina.valves.RemoteAddrValve" allow ="^.*$" /> </Context >
或限制特定IP :
1 2 3 4 <Context antiResourceLocking ="false" privileged ="true" > <Valve className ="org.apache.catalina.valves.RemoteAddrValve" allow ="192\.168\.1\.\d+|10\.0\.0\.\d+" /> </Context >
同样修改host-manager :
1 vim /application/tomcat/webapps/host-manager/META-INF/context.xml
8. Tomcat配置优化(内存、并发、缓存) 8.1 内存优化 8.1.1 JVM内存参数 catalina.sh配置 :
1 2 3 4 5 6 7 8 9 10 11 JAVA_OPTS='-server \ -Xms2048m \ -Xmx2048m \ -XX:NewSize=512m \ -XX:MaxNewSize=512m \ -XX:MetaspaceSize=256m \ -XX:MaxMetaspaceSize=256m \ -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 \ -XX:+HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath=/application/tomcat/logs/heap_dump.hprof'
内存分配原则 :
Xms和Xmx设置为相同值,避免动态调整
堆内存 = 物理内存的50%-70%
新生代 = 堆内存的1/3-1/4
元空间 = 256m-512m
8.1.2 验证内存配置 1 2 3 4 5 6 7 8 lsof -i:8080 | grep LISTEN jmap -heap <PID> jstat -gcutil <PID> 1000 10
8.2 并发优化 8.2.1 连接器并发配置 1 2 3 4 5 6 7 8 9 10 11 12 13 <Connector port ="8080" protocol ="HTTP/1.1" maxHttpHeaderSize ="8192" maxThreads ="1000" minSpareThreads ="100" maxSpareThreads ="500" minProcessors ="100" maxProcessors ="1000" enableLookups ="false" URIEncoding ="utf-8" acceptCount ="1000" connectionTimeout ="20000" redirectPort ="8443" disableUploadTimeout ="true" />
并发参数调优 :
参数
说明
计算公式
maxThreads
最大线程数
CPU核心数 × 200
minSpareThreads
最小空闲线程
maxThreads × 10%
maxSpareThreads
最大空闲线程
maxThreads × 50%
acceptCount
等待队列
maxThreads
connectionTimeout
连接超时
20000ms(20秒)
8.2.2 线程池配置(Tomcat 8.5+) 1 2 3 4 5 6 7 8 9 10 11 12 <Executor name ="tomcatThreadPool" namePrefix ="catalina-exec-" maxThreads ="1000" minSpareThreads ="100" maxIdleTime ="60000" /> <Connector port ="8080" protocol ="HTTP/1.1" executor ="tomcatThreadPool" connectionTimeout ="20000" redirectPort ="8443" />
8.3 缓存优化 8.3.1 启用压缩 1 2 3 4 5 6 <Connector port ="8080" protocol ="HTTP/1.1" compression ="on" compressionMinSize ="2048" compressableMimeType ="text/html,text/xml,text/javascript,text/css,text/plain,application/json" connectionTimeout ="20000" redirectPort ="8443" />
压缩参数说明 :
compression="on":启用压缩
compressionMinSize:最小压缩大小(2KB)
compressableMimeType:可压缩的MIME类型
8.3.2 静态资源缓存 在web.xml中配置 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <filter > <filter-name > ExpiresFilter</filter-name > <filter-class > org.apache.catalina.filters.ExpiresFilter</filter-class > <init-param > <param-name > ExpiresByType image</param-name > <param-value > access plus 1 month</param-value > </init-param > <init-param > <param-name > ExpiresByType text/css</param-name > <param-value > access plus 1 month</param-value > </init-param > <init-param > <param-name > ExpiresByType application/javascript</param-name > <param-value > access plus 1 month</param-value > </init-param > </filter > <filter-mapping > <filter-name > ExpiresFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping >
8.4 综合优化配置示例 8.4.1 生产环境推荐配置 server.xml Connector配置 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <Connector port ="8080" protocol ="HTTP/1.1" maxHttpHeaderSize ="8192" maxThreads ="1000" minSpareThreads ="100" maxSpareThreads ="500" minProcessors ="100" maxProcessors ="1000" enableLookups ="false" compression ="on" compressionMinSize ="2048" compressableMimeType ="text/html,text/xml,text/javascript,text/css,text/plain,application/json" connectionTimeout ="20000" URIEncoding ="utf-8" acceptCount ="1000" redirectPort ="8443" disableUploadTimeout ="true" />
catalina.sh JVM配置 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 JAVA_OPTS='-server \ -Xms2048m \ -Xmx2048m \ -XX:NewSize=512m \ -XX:MaxNewSize=512m \ -XX:MetaspaceSize=256m \ -XX:MaxMetaspaceSize=256m \ -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 \ -XX:G1HeapRegionSize=16m \ -XX:+DisableExplicitGC \ -XX:+HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath=/application/tomcat/logs/heap_dump.hprof \ -XX:+PrintGCDetails \ -XX:+PrintGCDateStamps \ -Xloggc:/application/tomcat/logs/gc.log'
9. 运维最佳实践 9.1 部署最佳实践
使用专用用户运行 :不要使用root用户
目录权限控制 :合理设置文件和目录权限
日志管理 :配置日志轮转,避免日志文件过大
监控告警 :配置进程监控和性能监控
备份配置 :定期备份配置文件和重要数据
9.2 性能优化最佳实践
JVM调优 :根据服务器资源合理配置JVM参数
连接器优化 :根据并发量调整线程数
启用压缩 :减少网络传输量
静态资源分离 :使用Nginx处理静态资源
缓存策略 :合理配置缓存,减少数据库压力
9.3 安全最佳实践
降权启动 :使用专用用户运行
端口保护 :限制管理端口访问
禁用管理端 :生产环境禁用或限制访问
删除示例 :删除示例应用和文档
启用HTTPS :生产环境使用HTTPS
定期更新 :及时更新Tomcat版本,修复安全漏洞
9.4 监控最佳实践
进程监控 :监控Tomcat进程状态
性能监控 :监控JVM内存、GC、线程等
日志监控 :监控错误日志和访问日志
业务监控 :监控应用响应时间和错误率
告警机制 :配置告警规则,及时发现问题
10. 总结 10.1 核心要点
安装部署 :正确安装JDK和Tomcat,配置环境变量
配置管理 :理解server.xml配置结构,合理配置各组件
应用部署 :掌握WAR包部署和自定义目录配置
多实例集群 :实现多实例部署和负载均衡
性能优化 :从内存、并发、缓存三个方面优化
安全加固 :降权启动、端口保护、禁用管理端
10.2 架构师建议
设计阶段 :
规划Tomcat实例数量和资源分配
设计负载均衡和会话保持方案
规划监控和告警机制
实施阶段 :
遵循安全最佳实践
合理配置JVM和连接器参数
配置日志和监控
运维阶段 :
10.3 学习路径
基础操作 :安装、启动、停止、日志查看
配置管理 :理解server.xml配置结构
应用部署 :WAR包部署、自定义配置
高级特性 :多实例、集群、性能优化
运维实践 :监控、调优、故障排查
相关文章 :