Tomcat 反向代理集成
Reverse Proxy Integration
概述
反向代理是企业Web架构的重要组成部分,能够提供负载均衡、SSL终止、缓存和安全防护等功能。本文详细介绍Tomcat与Nginx、Apache HTTP Server、HAProxy等反向代理的集成配置。
1. Nginx反向代理集成
1.1 基础反向代理配置
# nginx.conf - 基础反向代理配置
upstream tomcat_backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://tomcat_backend;
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 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
# 缓冲设置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
}
}
1.2 Tomcat AJP配置
<!-- server.xml - AJP连接器配置 -->
<Connector port="8009"
protocol="org.apache.coyote.ajp.AjpNioProtocol"
maxThreads="200"
minSpareThreads="10"
acceptCount="100"
connectionTimeout="600000"
secretRequired="true"
secret="ajp_secret_2023"
address="127.0.0.1" />
# Nginx AJP配置(需要编译ajp模块)
upstream tomcat_ajp {
server 127.0.0.1:8009;
keepalive 32;
}
server {
listen 80;
server_name app.example.com;
location / {
ajp_pass tomcat_ajp;
ajp_cache_size 1000;
ajp_temp_path /tmp/ajp_temp;
}
}
1.3 负载均衡配置
# 高级负载均衡配置
upstream tomcat_cluster {
# 负载均衡策略
least_conn;
# 后端服务器
server 192.168.1.10:8080 weight=3 max_fails=2 fail_timeout=30s;
server 192.168.1.11:8080 weight=2 max_fails=2 fail_timeout=30s;
server 192.168.1.12:8080 weight=1 max_fails=2 fail_timeout=30s backup;
# 健康检查
keepalive 32;
keepalive_requests 1000;
keepalive_timeout 60s;
}
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://tomcat_cluster;
# 会话粘性(如果需要)
proxy_cookie_path / "/; Secure; HttpOnly";
# 请求头设置
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_set_header X-Forwarded-Port $server_port;
# 性能优化
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_cache_bypass $http_upgrade;
# 错误处理
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
proxy_next_upstream_timeout 0;
proxy_next_upstream_tries 3;
}
# 静态文件直接服务
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ {
root /var/www/static;
expires 1y;
add_header Cache-Control "public, immutable";
}
# API路径特殊处理
location /api/ {
proxy_pass http://tomcat_cluster;
proxy_buffering off;
proxy_request_buffering off;
}
}
2. Apache HTTP Server集成
2.1 mod_proxy配置
# httpd.conf - mod_proxy配置
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
<VirtualHost *:80>
ServerName example.com
# 代理配置
ProxyPreserveHost On
ProxyPassMatch ^/(.*\.jsp)$ http://localhost:8080/$1
ProxyPassMatch ^/servlet(.*)$ http://localhost:8080/servlet$1
ProxyPass /app/ http://localhost:8080/app/
ProxyPassReverse /app/ http://localhost:8080/app/
# 静态文件直接服务
DocumentRoot /var/www/html
<Directory "/var/www/html">
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
2.2 mod_jk配置
# 加载mod_jk模块
LoadModule jk_module modules/mod_jk.so
# JK配置
JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
# 映射配置
JkMount /servlet/* worker1
JkMount /*.jsp worker1
JkMount /app/* loadbalancer
workers.properties配置:
# workers.properties
worker.list=worker1,worker2,loadbalancer
# Worker 1
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
worker.worker1.connection_pool_size=10
worker.worker1.connection_pool_minsize=5
worker.worker1.connection_pool_timeout=600
# Worker 2
worker.worker2.type=ajp13
worker.worker2.host=localhost
worker.worker2.port=8010
worker.worker2.connection_pool_size=10
# 负载均衡器
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=worker1,worker2
worker.loadbalancer.sticky_session=1
3. HAProxy集成
3.1 基础HAProxy配置
# haproxy.cfg
global
daemon
maxconn 4096
log stdout local0 info
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
option httplog
option dontlognull
retries 3
# 前端配置
frontend tomcat_frontend
bind *:80
bind *:443 ssl crt /etc/ssl/certs/example.com.pem
# 重定向HTTP到HTTPS
redirect scheme https if !{ ssl_fc }
# ACL规则
acl is_api path_beg /api/
acl is_admin path_beg /admin/
# 路由规则
use_backend api_backend if is_api
use_backend admin_backend if is_admin
default_backend web_backend
# 后端配置
backend web_backend
balance roundrobin
option httpchk GET /health
server tomcat1 192.168.1.10:8080 check inter 2000 rise 2 fall 3
server tomcat2 192.168.1.11:8080 check inter 2000 rise 2 fall 3
server tomcat3 192.168.1.12:8080 check inter 2000 rise 2 fall 3 backup
backend api_backend
balance leastconn
option httpchk GET /api/health
server api1 192.168.1.20:8080 check
server api2 192.168.1.21:8080 check
backend admin_backend
balance source
option httpchk GET /admin/ping
server admin1 192.168.1.30:8080 check
3.2 会话粘性配置
# 会话粘性配置
backend web_backend_sticky
balance source
hash-type consistent
# Cookie粘性
cookie SERVERID insert indirect nocache
server tomcat1 192.168.1.10:8080 check cookie s1
server tomcat2 192.168.1.11:8080 check cookie s2
server tomcat3 192.168.1.12:8080 check cookie s3
4. Tomcat配置优化
4.1 反向代理适配配置
<!-- server.xml - 反向代理适配 -->
<Engine name="Catalina" defaultHost="localhost">
<!-- 访问日志记录真实IP -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern='%{X-Forwarded-For}i %l %u %t "%r" %s %b %D "%{Referer}i" "%{User-Agent}i"' />
<!-- 远程IP阀门 -->
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
proxiesHeader="X-Forwarded-By"
trustedProxies="127\.0\.0\.1|192\.168\..*"
protocolHeader="X-Forwarded-Proto" />
<Host name="localhost" appBase="webapps">
<!-- Host配置 -->
</Host>
</Engine>
4.2 连接器优化
<!-- HTTP连接器优化 -->
<Connector port="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="200"
acceptCount="100"
connectionTimeout="20000"
<!-- 反向代理优化 -->
maxKeepAliveRequests="100"
keepAliveTimeout="60000"
compression="on"
compressionMinSize="2048"
compressibleMimeType="text/html,text/xml,text/css,application/javascript,application/json"
<!-- 安全设置 -->
server="Apache"
xpoweredBy="false" />
5. SSL终止配置
5.1 Nginx SSL终止
server {
listen 443 ssl http2;
server_name secure.example.com;
# SSL配置
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
proxy_pass http://127.0.0.1:8080;
# SSL头设置
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-SSL on;
proxy_set_header X-Forwarded-Port 443;
# 其他代理头
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
# HTTP重定向
server {
listen 80;
server_name secure.example.com;
return 301 https://$server_name$request_uri;
}
5.2 Tomcat SSL感知配置
<!-- Tomcat感知SSL终止 -->
<Connector port="8080"
protocol="HTTP/1.1"
<!-- SSL终止配置 -->
scheme="https"
secure="true"
proxyPort="443" />
6. 健康检查配置
6.1 Tomcat健康检查端点
// HealthCheckServlet.java
package com.example.health;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
public class HealthCheckServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
// 检查应用健康状态
boolean isHealthy = checkApplicationHealth();
if (isHealthy) {
response.setStatus(200);
response.setContentType("application/json");
PrintWriter out = response.getWriter();
out.println("{");
out.println(" \"status\": \"UP\",");
out.println(" \"timestamp\": " + System.currentTimeMillis() + ",");
out.println(" \"checks\": {");
out.println(" \"database\": \"" + checkDatabase() + "\",");
out.println(" \"memory\": \"" + checkMemory() + "\",");
out.println(" \"disk\": \"" + checkDisk() + "\"");
out.println(" }");
out.println("}");
} else {
response.setStatus(503);
response.getWriter().println("{\"status\": \"DOWN\"}");
}
} catch (Exception e) {
response.setStatus(500);
response.getWriter().println("{\"status\": \"ERROR\", \"message\": \"" + e.getMessage() + "\"}");
}
}
private boolean checkApplicationHealth() {
return checkDatabase().equals("UP") &&
checkMemory().equals("UP") &&
checkDisk().equals("UP");
}
private String checkDatabase() {
// 数据库连接检查
try {
// 检查数据库连接
return "UP";
} catch (Exception e) {
return "DOWN";
}
}
private String checkMemory() {
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
long usedMemory = runtime.totalMemory() - runtime.freeMemory();
double memoryUsage = (double) usedMemory / maxMemory;
return memoryUsage < 0.9 ? "UP" : "DOWN";
}
private String checkDisk() {
// 磁盘空间检查
return "UP";
}
}
6.2 健康检查配置
<!-- web.xml - 健康检查配置 -->
<servlet>
<servlet-name>HealthCheckServlet</servlet-name>
<servlet-class>com.example.health.HealthCheckServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HealthCheckServlet</servlet-name>
<url-pattern>/health</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>HealthCheckServlet</servlet-name>
<url-pattern>/ping</url-pattern>
</servlet-mapping>
7. 监控和日志集成
7.1 访问日志统一
<!-- Tomcat访问日志配置 -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="access_log"
suffix=".txt"
pattern='%{X-Forwarded-For}i - %u %t "%r" %s %b %D "%{Referer}i" "%{User-Agent}i" "%{X-Request-ID}i"'
rotatable="true"
maxDays="30" />
7.2 反向代理监控脚本
#!/bin/bash
# reverse-proxy-monitor.sh
NGINX_STATUS_URL="http://localhost/nginx_status"
TOMCAT_HEALTH_URL="http://localhost:8080/health"
check_nginx_status() {
echo "=== Nginx状态检查 ==="
if curl -s "$NGINX_STATUS_URL" > /dev/null; then
echo "✓ Nginx运行正常"
# 获取连接统计
curl -s "$NGINX_STATUS_URL" | while read line; do
echo " $line"
done
else
echo "✗ Nginx状态检查失败"
fi
}
check_tomcat_health() {
echo "=== Tomcat健康检查 ==="
response=$(curl -s -w "%{http_code}" "$TOMCAT_HEALTH_URL")
http_code=${response: -3}
if [ "$http_code" = "200" ]; then
echo "✓ Tomcat健康状态正常"
echo "$response" | head -n -1 | python -m json.tool 2>/dev/null
else
echo "✗ Tomcat健康检查失败 (HTTP $http_code)"
fi
}
check_upstream_status() {
echo "=== 后端服务器状态 ==="
# 检查各个后端服务器
backends=("192.168.1.10:8080" "192.168.1.11:8080" "192.168.1.12:8080")
for backend in "${backends[@]}"; do
if curl -s -m 5 "http://$backend/health" > /dev/null; then
echo "✓ $backend 可访问"
else
echo "✗ $backend 不可访问"
fi
done
}
main() {
echo "反向代理监控报告 - $(date)"
echo "================================================"
check_nginx_status
echo
check_tomcat_health
echo
check_upstream_status
echo
echo "监控完成"
}
case "$1" in
"nginx") check_nginx_status ;;
"tomcat") check_tomcat_health ;;
"upstream") check_upstream_status ;;
*) main ;;
esac
小结
通过本文学习,你应该掌握:
- Nginx与Tomcat的反向代理集成配置
- Apache HTTP Server的mod_proxy和mod_jk配置
- HAProxy负载均衡和会话粘性配置
- Tomcat反向代理适配和优化设置
- SSL终止配置和安全头设置
- 健康检查端点的实现和配置
- 反向代理监控和日志集成
下一篇文章将介绍Tomcat容器化部署技术。