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

小结

通过本文学习,你应该掌握:

  1. Nginx与Tomcat的反向代理集成配置
  2. Apache HTTP Server的mod_proxy和mod_jk配置
  3. HAProxy负载均衡和会话粘性配置
  4. Tomcat反向代理适配和优化设置
  5. SSL终止配置和安全头设置
  6. 健康检查端点的实现和配置
  7. 反向代理监控和日志集成

下一篇文章将介绍Tomcat容器化部署技术。

powered by Gitbook© 2025 编外计划 | 最后修改: 2025-08-29 15:40:15

results matching ""

    No results matching ""