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