Apache 反向代理 #

反向代理概述 #

什么是反向代理? #

text
┌─────────────────────────────────────────────────────────────┐
│                    反向代理概念                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  正向代理:                                                 │
│  客户端 ──> 代理服务器 ──> 目标服务器                       │
│  (客户端知道目标服务器,代理帮助访问)                      │
│                                                             │
│  反向代理:                                                 │
│  客户端 ──> 反向代理 ──> 后端服务器                         │
│  (客户端不知道后端服务器,代理代表服务器)                  │
│                                                             │
│  ┌─────────┐         ┌─────────────┐         ┌─────────┐   │
│  │  客户端  │ ──────> │ 反向代理    │ ──────> │后端服务 │   │
│  └─────────┘         │ (Apache)    │         │ :3000   │   │
│                      │             │ ──────> │后端服务 │   │
│                      │             │         │ :8000   │   │
│                      └─────────────┘         └─────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

反向代理的作用 #

text
┌─────────────────────────────────────────────────────────────┐
│                    反向代理的作用                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 负载均衡                                                │
│     将请求分发到多个后端服务器                              │
│                                                             │
│  2. 隐藏后端服务器                                          │
│     保护后端服务器不被直接访问                              │
│                                                             │
│  3. SSL 终止                                                │
│     在代理层处理 HTTPS,后端使用 HTTP                       │
│                                                             │
│  4. 缓存                                                    │
│     缓存后端响应,减轻后端压力                              │
│                                                             │
│  5. 压缩                                                    │
│     统一处理响应压缩                                        │
│                                                             │
│  6. 路由                                                    │
│     根据路径将请求转发到不同服务                            │
│                                                             │
│  7. 安全                                                    │
│     统一的安全策略,如访问控制、限流                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

启用代理模块 #

加载必要模块 #

bash
# Ubuntu/Debian
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod proxy_wstunnel
sudo a2enmod lbmethod_byrequests
sudo a2enmod headers
sudo a2enmod rewrite

# 重启 Apache
sudo systemctl restart apache2

模块说明 #

text
┌─────────────────────────────────────────────────────────────┐
│                    代理模块说明                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  proxy            代理核心模块                              │
│  proxy_http       HTTP 代理支持                             │
│  proxy_ajp        AJP 协议支持(Tomcat)                    │
│  proxy_fcgi       FastCGI 代理支持                          │
│  proxy_wstunnel   WebSocket 代理支持                        │
│  proxy_balancer   负载均衡支持                              │
│  lbmethod_byrequests    请求数负载均衡                      │
│  lbmethod_bytraffic     流量负载均衡                        │
│  lbmethod_bybusyness    忙碌度负载均衡                      │
│  lbmethod_heartbeat     心跳负载均衡                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

基础代理配置 #

简单反向代理 #

apache
# ============================================
# 简单反向代理配置
# ============================================

<VirtualHost *:80>
    ServerName api.example.com
    
    # 代理所有请求到后端服务
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    # 保留原始主机名
    ProxyPreserveHost On
</VirtualHost>

ProxyPass 指令详解 #

apache
# ============================================
# ProxyPass 语法
# ============================================

# 基本语法
# ProxyPass [路径] [目标URL] [参数]

# 示例
ProxyPass / http://localhost:3000/
ProxyPass /api http://localhost:8000/api
ProxyPass /images http://localhost:9000/images

# 带参数
ProxyPass / http://localhost:3000/ retry=5 timeout=60

# 常用参数
# retry=5         重试次数
# timeout=60      超时时间(秒)
# connectiontimeout=10  连接超时
# keepalive=On    保持连接
# min=5           最小连接数
# max=20          最大连接数
# smax=10         最大软连接数
# acquire=3000    获取连接超时(毫秒)
# disablereuse=On 禁用连接重用

ProxyPassReverse #

apache
# ============================================
# ProxyPassReverse 说明
# ============================================

# ProxyPassReverse 用于修正后端返回的重定向 URL
# 将后端的 URL 替换为代理服务器的 URL

<VirtualHost *:80>
    ServerName example.com
    
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    # 如果后端返回 Location: http://localhost:3000/login
    # 会被修正为 Location: http://example.com/login
</VirtualHost>

路径代理配置 #

多路径代理 #

apache
# ============================================
# 多路径代理配置
# ============================================

<VirtualHost *:80>
    ServerName example.com
    
    # API 请求代理到 Node.js
    ProxyPass /api http://localhost:3000/api
    ProxyPassReverse /api http://localhost:3000/api
    
    # 管理后台代理到 Python
    ProxyPass /admin http://localhost:8000/admin
    ProxyPassReverse /admin http://localhost:8000/admin
    
    # 静态资源代理到文件服务器
    ProxyPass /static http://localhost:9000/static
    ProxyPassReverse /static http://localhost:9000/static
    
    # 其他请求代理到主服务
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/
</VirtualHost>

路径匹配顺序 #

apache
# ============================================
# 路径匹配顺序(重要!)
# ============================================

# 注意:更具体的路径应该放在前面

<VirtualHost *:80>
    ServerName example.com
    
    # 错误示例(/api 会被 / 匹配)
    # ProxyPass / http://localhost:8080/
    # ProxyPass /api http://localhost:3000/api
    
    # 正确示例(具体路径在前)
    ProxyPass /api http://localhost:3000/api
    ProxyPass /admin http://localhost:8000/admin
    ProxyPass / http://localhost:8080/
    
    ProxyPassReverse /api http://localhost:3000/api
    ProxyPassReverse /admin http://localhost:8000/admin
    ProxyPassReverse / http://localhost:8080/
</VirtualHost>

排除特定路径 #

apache
# ============================================
# 排除特定路径
# ============================================

<VirtualHost *:80>
    ServerName example.com
    
    # 静态文件不代理,直接由 Apache 处理
    ProxyPass /static !
    
    # 本地路径
    Alias /static /var/www/static
    <Directory /var/www/static>
        Require all granted
    </Directory>
    
    # 其他请求代理
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>

负载均衡配置 #

基础负载均衡 #

apache
# ============================================
# 负载均衡配置
# ============================================

<Proxy "balancer://mycluster">
    BalancerMember "http://server1:3000"
    BalancerMember "http://server2:3000"
    BalancerMember "http://server3:3000"
</Proxy>

<VirtualHost *:80>
    ServerName example.com
    
    ProxyPass / balancer://mycluster/
    ProxyPassReverse / balancer://mycluster/
</VirtualHost>

负载均衡算法 #

apache
# ============================================
# 负载均衡算法
# ============================================

# 1. 轮询(默认)
<Proxy "balancer://roundrobin">
    BalancerMember "http://server1:3000"
    BalancerMember "http://server2:3000"
    BalancerMember "http://server3:3000"
</Proxy>

# 2. 加权轮询
<Proxy "balancer://weighted">
    BalancerMember "http://server1:3000" loadfactor=3
    BalancerMember "http://server2:3000" loadfactor=2
    BalancerMember "http://server3:3000" loadfactor=1
    # loadfactor 越大,分配的请求越多
</Proxy>

# 3. 最少请求
<Proxy "balancer://leastconn" lbmethod=bybusyness>
    BalancerMember "http://server1:3000"
    BalancerMember "http://server2:3000"
    BalancerMember "http://server3:3000"
</Proxy>

# 4. 流量均衡
<Proxy "balancer://traffic" lbmethod=bytraffic>
    BalancerMember "http://server1:3000"
    BalancerMember "http://server2:3000"
</Proxy>

健康检查 #

apache
# ============================================
# 健康检查配置
# ============================================

<Proxy "balancer://healthcheck">
    # 启用故障转移
    BalancerMember "http://server1:3000" retry=5
    BalancerMember "http://server2:3000" retry=5
    BalancerMember "http://server3:3000" retry=5
    
    # 设置超时
    ProxySet timeout=60
    ProxySet connectiontimeout=10
</Proxy>

<VirtualHost *:80>
    ServerName example.com
    
    ProxyPass / balancer://healthcheck/
    ProxyPassReverse / balancer://healthcheck/
    
    # 故障转移页面
    ErrorDocument 502 /maintenance.html
    ErrorDocument 503 /maintenance.html
</VirtualHost>

会话保持 #

apache
# ============================================
# 会话保持(Sticky Session)
# ============================================

<Proxy "balancer://sticky">
    # 基于 Cookie 的会话保持
    BalancerMember "http://server1:3000" route=server1
    BalancerMember "http://server2:3000" route=server2
    BalancerMember "http://server3:3000" route=server3
    
    ProxySet stickysession=SERVERID
</Proxy>

<VirtualHost *:80>
    ServerName example.com
    
    ProxyPass / balancer://sticky/
    ProxyPassReverse / balancer://sticky/
    
    # 后端需要设置 Cookie: SERVERID=server1
</VirtualHost>

WebSocket 代理 #

WebSocket 代理配置 #

apache
# ============================================
# WebSocket 代理配置
# ============================================

# 加载 WebSocket 模块
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

<VirtualHost *:80>
    ServerName example.com
    
    # WebSocket 代理
    ProxyPass /ws ws://localhost:3000/ws
    ProxyPassReverse /ws ws://localhost:3000/ws
    
    # 普通 HTTP 代理
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>

Socket.IO 代理 #

apache
# ============================================
# Socket.IO 代理配置
# ============================================

<VirtualHost *:80>
    ServerName example.com
    
    # 启用 WebSocket 升级
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /socket.io/(.*) ws://localhost:3000/socket.io/$1 [P,L]
    
    # 普通 HTTP 请求
    ProxyPass /socket.io http://localhost:3000/socket.io
    ProxyPassReverse /socket.io http://localhost:3000/socket.io
    
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>

代理高级配置 #

请求头处理 #

apache
# ============================================
# 请求头处理
# ============================================

<VirtualHost *:80>
    ServerName example.com
    
    # 保留原始主机名
    ProxyPreserveHost On
    
    # 添加自定义请求头
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    <Location />
        # 添加客户端 IP
        RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
        
        # 添加协议
        RequestHeader set X-Forwarded-Proto "%{REQUEST_SCHEME}s"
        
        # 添加主机名
        RequestHeader set X-Forwarded-Host "%{HTTP_HOST}s"
        
        # 添加端口
        RequestHeader set X-Forwarded-Port "%{SERVER_PORT}s"
    </Location>
</VirtualHost>

超时配置 #

apache
# ============================================
# 超时配置
# ============================================

<VirtualHost *:80>
    ServerName example.com
    
    # 全局代理超时
    ProxyTimeout 300
    
    ProxyPass / http://localhost:3000/ \
        connectiontimeout=10 \
        timeout=300 \
        retry=5
    
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>

连接池配置 #

apache
# ============================================
# 连接池配置
# ============================================

<VirtualHost *:80>
    ServerName example.com
    
    ProxyPass / http://localhost:3000/ \
        min=5 \
        smax=10 \
        max=20 \
        acquire=3000 \
        keepalive=On \
        retry=5 \
        timeout=60
    
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>

SSL 终止 #

HTTPS 代理到 HTTP 后端 #

apache
# ============================================
# SSL 终止配置
# ============================================

<VirtualHost *:443>
    ServerName example.com
    
    # SSL 配置
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/example.com.crt
    SSLCertificateKeyFile /etc/ssl/private/example.com.key
    
    # 代理到 HTTP 后端
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    # 添加 HTTPS 标识
    RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>

# HTTP 重定向到 HTTPS
<VirtualHost *:80>
    ServerName example.com
    Redirect permanent / https://example.com/
</VirtualHost>

代理缓存 #

启用代理缓存 #

apache
# ============================================
# 代理缓存配置
# ============================================

# 加载缓存模块
LoadModule cache_module modules/mod_cache.so
LoadModule cache_disk_module modules/mod_cache_disk.so

# 缓存根目录
CacheRoot /var/cache/apache2/proxy
CacheDirLevels 2
CacheDirLength 1
CacheMaxFileSize 10000000
CacheMaxFileSize 10000000

<VirtualHost *:80>
    ServerName example.com
    
    # 启用缓存
    CacheQuickHandler on
    CacheLock on
    CacheLockPath /tmp/cachelock
    CacheLockMaxAge 5
    
    # 缓存配置
    <Location />
        CacheEnable disk
        CacheHeader on
        CacheDefaultExpire 3600
        CacheMaxExpire 86400
        CacheLastModifiedFactor 0.5
        CacheIgnoreHeaders Set-Cookie
    </Location>
    
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>

完整配置示例 #

微服务网关配置 #

apache
# ============================================
# 微服务网关配置
# ============================================

<VirtualHost *:80>
    ServerName api.example.com
    
    # 用户服务
    ProxyPass /users http://user-service:3001/users
    ProxyPassReverse /users http://user-service:3001/users
    
    # 订单服务
    ProxyPass /orders http://order-service:3002/orders
    ProxyPassReverse /orders http://order-service:3002/orders
    
    # 产品服务
    ProxyPass /products http://product-service:3003/products
    ProxyPassReverse /products http://product-service:3003/products
    
    # WebSocket 服务
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /ws/(.*) ws://ws-service:3004/ws/$1 [P,L]
    
    ProxyPass /ws http://ws-service:3004/ws
    ProxyPassReverse /ws http://ws-service:3004/ws
    
    # 默认代理
    ProxyPass / http://gateway-service:3000/
    ProxyPassReverse / http://gateway-service:3000/
    
    # 请求头
    ProxyPreserveHost On
    RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
    RequestHeader set X-Forwarded-Proto "%{REQUEST_SCHEME}s"
    
    # 日志
    ErrorLog ${APACHE_LOG_DIR}/api-error.log
    CustomLog ${APACHE_LOG_DIR}/api-access.log combined
</VirtualHost>

Node.js 应用代理 #

apache
# ============================================
# Node.js 应用代理
# ============================================

<VirtualHost *:80>
    ServerName nodeapp.example.com
    
    # 静态文件由 Apache 处理
    Alias /static /var/www/nodeapp/public
    <Directory /var/www/nodeapp/public>
        Options -Indexes +FollowSymLinks
        Require all granted
        
        # 缓存静态资源
        <IfModule mod_expires.c>
            ExpiresActive On
            ExpiresByType text/css "access plus 1 year"
            ExpiresByType application/javascript "access plus 1 year"
            ExpiresByType image/* "access plus 1 year"
        </IfModule>
    </Directory>
    
    # API 和动态请求代理到 Node.js
    ProxyPass /static !
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
    
    # WebSocket 支持
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*) ws://localhost:3000/$1 [P,L]
    
    # 超时配置
    ProxyTimeout 300
    
    # 日志
    ErrorLog ${APACHE_LOG_DIR}/nodeapp-error.log
    CustomLog ${APACHE_LOG_DIR}/nodeapp-access.log combined
</VirtualHost>

下一步 #

掌握了反向代理配置后,继续学习 URL 重写,了解如何使用 mod_rewrite 模块实现 URL 重写和重定向!

最后更新:2026-03-29