一、为什么需要Tomcat负载均衡?
Tomcat是Apache软件基金会开发的轻量级Java应用服务器,广泛用于部署Java Web应用。当单台Tomcat服务器无法处理高并发请求时,需要配置负载均衡来:
- 提高并发处理能力:多台Tomcat服务器并行处理请求
- 实现高可用性:一台服务器故障时,其他服务器继续提供服务
- 实现水平扩展:根据业务增长动态添加Tomcat服务器
- 优化资源利用:将请求均匀分配到多台服务器
二、Tomcat负载均衡架构
典型的Tomcat负载均衡架构如下:
客户端请求 → 负载均衡器(Nginx/Apache) → 多台Tomcat服务器
负载均衡器选型:
| 负载均衡器 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Nginx | 轻量、高性能、配置简单 | 功能相对简单 | 中小规模集群 |
| Apache HTTP Server | 功能丰富、支持多种协议 | 配置复杂、性能略低 | 企业级应用 |
| HAProxy | 专业的负载均衡软件 | 需要单独学习 | 大规模集群 |
| 硬件负载均衡器(F5、Array) | 性能极高、功能全面 | 价格昂贵 | 关键业务系统 |
三、使用Nginx实现Tomcat负载均衡
3.1 安装Nginx
# CentOS 7安装Nginx
yum install -y epel-release
yum install -y nginx
# 启动Nginx
systemctl enable nginx
systemctl start nginx
3.2 配置Tomcat服务器集群
假设有3台Tomcat服务器:
– Tomcat1: 192.168.1.101:8080
– Tomcat2: 192.168.1.102:8080
– Tomcat3: 192.168.1.103:8080
3.3 配置Nginx负载均衡
编辑Nginx配置文件(/etc/nginx/nginx.conf 或 /etc/nginx/conf.d/tomcat.conf):
# 定义Tomcat服务器集群
upstream tomcat_cluster {
# 负载均衡策略:轮询(默认)
server 192.168.1.101:8080 weight=1;
server 192.168.1.102:8080 weight=1;
server 192.168.1.103:8080 weight=1;
# 可选:IP哈希策略(保持会话)
# ip_hash;
# 可选:最少连接策略
# least_conn;
}
# 配置负载均衡服务器
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://tomcat_cluster;
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;
}
}
3.4 负载均衡策略详解
1. 轮询(默认):
upstream tomcat_cluster {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}
请求按顺序分配到每台服务器。
2. 权重(weight):
upstream tomcat_cluster {
server 192.168.1.101:8080 weight=2;
server 192.168.1.102:8080 weight=1;
}
性能高的服务器分配更多请求。
3. IP哈希(ip_hash):
upstream tomcat_cluster {
ip_hash;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}
同一IP的请求总是分配到同一台服务器(保持会话)。
4. 最少连接(least_conn):
upstream tomcat_cluster {
least_conn;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}
请求分配到当前连接数最少的服务器。
四、会话保持配置
4.1 问题:负载均衡导致会话丢失
当使用轮询或最少连接策略时,同一用户的多次请求可能被分配到不同服务器,导致会话丢失。
4.2 解决方案1:IP哈希策略
upstream tomcat_cluster {
ip_hash;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}
优点:配置简单
缺点:可能导致负载不均
4.3 解决方案2:Tomcat集群会话复制
在每台Tomcat的server.xml中配置集群:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
在应用的web.xml中配置:
<web-app>
<display-name>Tomcat Cluster Test</display-name>
<distributable/>
</web-app>
4.4 解决方案3:使用Redis存储会话
安装Redis:
yum install -y redis
systemctl enable redis
systemctl start redis
配置Tomcat使用Redis存储会话:
- 下载
tomcat-redis-session-manager库 - 将JAR文件放到Tomcat的
lib/目录 - 在
context.xml中配置:
<Context>
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve"/>
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
host="localhost"
port="6379"
database="0"
maxInactiveInterval="60"/>
</Context>
五、健康检查配置
5.1 Nginx健康检查
使用max_fails和fail_timeout参数:
upstream tomcat_cluster {
server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.103:8080 backup; # 备份服务器
}
参数说明:
– max_fails:在fail_timeout时间内允许的最大失败次数
– fail_timeout:服务器被认为不可用的时间
– backup:备份服务器,主服务器都故障时才使用
– down:标记服务器为永久不可用
5.2 主动健康检查(需要Nginx Plus或第三方模块)
# 使用nginx_upstream_check_module模块
upstream tomcat_cluster {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_http_send "HEAD /health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
六、SSL终止配置
在负载均衡器上终止SSL,减轻Tomcat服务器的计算负担。
6.1 使用Let’s Encrypt免费SSL证书
# 安装certbot
yum install -y certbot python3-certbot-nginx
# 获取SSL证书
certbot --nginx -d example.com -d www.example.com
# 自动续期
systemctl enable certbot-renew.timer
6.2 配置Nginx SSL终止
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://tomcat_cluster;
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;
}
}
# HTTP重定向到HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
七、性能优化
7.1 Nginx性能优化
# /etc/nginx/nginx.conf
worker_processes auto; # 自动设置为CPU核心数
worker_connections 10240; # 每个worker进程的最大连接数
# 开启gzip压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
gzip_min_length 1024;
# 开启缓存
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=tomcat_cache:10m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";
server {
location / {
proxy_cache tomcat_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_pass http://tomcat_cluster;
}
}
7.2 Tomcat性能优化
优化server.xml:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="500"
minSpareThreads="50"
acceptCount="100"
connectionTimeout="20000"
enableLookups="false"
compression="on"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,application/json"/>
优化catalina.sh:
# 设置JVM参数
CATALINA_OPTS="$CATALINA_OPTS -Xms2048m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512m"
CATALINA_OPTS="$CATALINA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
八、监控与日志
8.1 监控Nginx状态
# 在nginx.conf中开启状态页面
server {
listen 8080;
server_name localhost;
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
访问 http://localhost:8080/nginx_status 查看状态。
8.2 监控Tomcat性能
使用JMX监控:
- 在Tomcat的
catalina.sh中启用JMX:
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.port=9999"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
- 使用JConsole或VisualVM连接JMX端口监控。
8.3 集中式日志管理
配置Tomcat输出JSON格式日志:
在logging.properties中配置:
handlers = org.apache.juli.AsyncFileHandler, java.util.logging.ConsoleHandler
.org.apache.juli.AsyncFileHandler.level = FINE
.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
.org.apache.juli.AsyncFileHandler.prefix = catalina.
使用Filebeat发送日志到ELK:
# /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /opt/tomcat/logs/*.log
json.keys_under_root: true
output.logstash:
hosts: ["logstash:5044"]
九、常见问题与解决方案
Q1:负载均衡后会话丢失?
A:配置会话保持。可以使用IP哈希、Tomcat集群会话复制或Redis存储会话。
Q2:一台Tomcat服务器故障后,请求仍然转发到该服务器?
A:配置健康检查。使用max_fails和fail_timeout参数,或使用第三方模块实现主动健康检查。
Q3:负载均衡后性能反而下降?
A:可能是负载均衡器成为瓶颈。优化Nginx配置(开启gzip、缓存),或增加负载均衡器。
Q4:如何平滑下线一台Tomcat服务器?
A:使用Nginx的down参数标记服务器为不可用,等待当前请求处理完成后再下线。
upstream tomcat_cluster {
server 192.168.1.101:8080 down; # 平滑下线
server 192.168.1.102:8080;
}
十、总结
在CentOS环境下配置Tomcat负载均衡需要掌握以下核心技能:
- 架构设计:根据业务需求选择合适的负载均衡器
- 配置Nginx:定义upstream、配置负载均衡策略
- 会话保持:IP哈希、Tomcat集群、Redis存储
- 健康检查:被动检查、主动检查
- SSL终止:在负载均衡器上终止SSL
- 性能优化:Nginx优化、Tomcat优化
- 监控日志:监控Nginx状态、Tomcat性能、集中式日志
关键注意事项:
– 根据业务需求选择合适的负载均衡策略
– 务必配置健康检查,避免请求转发到故障服务器
– 使用会话保持机制,避免会话丢失
– 定期监控服务器性能,及时发现瓶颈
– 配置集中式日志管理,方便故障排查
通过本文的指南,你可以熟练地在CentOS环境下配置Tomcat负载均衡,实现高可用、高性能的Java Web应用部署。
注:本文基于CentOS 7/8和Tomcat 9/10编写,具体配置可能因版本差异而略有不同。