当你的应用跑在Tomcat、Node.js或者内网的某台服务器上,又希望用户只通过80或443端口访问时,反向代理就成了刚需。Apache作为老牌Web服务器,其mod_proxy模块族功能完善,配置起来也相对直观。本文将系统讲解Apache反向代理的配置方法、典型场景以及踩坑后的解决办法,读完基本能覆盖日常使用的绝大部分需求。

一、反向代理的基础原理与模块准备
1. 什么是反向代理
正向代理代替客户端去访问外部资源,服务端不知道真实客户端是谁;反向代理则相反,它代替后端服务接收请求,客户端并不知道(也不需要知道)真正的业务服务在哪里。对用户来说,访问的是api.ippipp.com,实际上请求可能被转发到了内网192.168.1.10:8080上的某个Java服务。
使用反向代理的常见动机包括:隐藏后端服务真实地址、统一HTTPS入口、实现负载均衡、做缓存加速、以及让多个不同的后端应用共用同一个域名下的不同路径。
2. 加载必要的模块
Apache的反向代理能力由一系列模块提供,最核心的是mod_proxy,再根据后端协议按需加载对应子模块。以CentOS下的Apache 2.4为例:
# 编辑配置文件,取消以下模块的注释(去掉前面的#) 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 proxy_wstunnel_module modules/mod_proxy_wstunnel.so LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
Ubuntu或Debian系统可以直接用a2enmod命令启用:
a2enmod proxy a2enmod proxy_http a2enmod proxy_balancer a2enmod proxy_wstunnel systemctl restart apache2
配置完务必执行httpd -M或apachectl -M查看已加载模块列表,确认proxy_module和proxy_http_module都在其中,否则后续的ProxyPass指令会直接导致Apache启动失败。
二、ProxyPass核心配置实战
1. 最简单的HTTP反向代理
把根路径下的所有请求转发到本机8080端口,只需要两行指令:
<VirtualHost *:80>
ServerName www.ipipp.com
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>
ProxyPass负责把请求转发出去,ProxyPassReverse则用于修改后端返回的Location响应头,防止重定向时把内网地址暴露给用户。这两条指令建议成对出现,很多重定向异常的问题都源于只写了ProxyPass。
ProxyPreserveHost On表示把原始的Host头传给后端,绝大多数基于域名的Web框架(如Spring、Django)都依赖这个头做路由或生成绝对链接,不加这句经常会出现页面能访问但样式错乱、跳转地址错误的情况。
2. 只代理特定路径
如果只想把api路径交给后端服务,其余请求仍由Apache自己处理,可以这样写:
<VirtualHost *:80>
ServerName www.ipipp.com
DocumentRoot /var/www/html
ProxyPass /api http://127.0.0.1:8080/api
ProxyPassReverse /api http://127.0.0.1:8080/api
# 排除某些子路径,用感叹号表示不代理
ProxyPass /api/static !
</VirtualHost>
注意路径匹配是按顺序进行的,排除规则ProxyPass /api/static !必须写在更宽泛的ProxyPass /api之前才能生效,这个顺序问题极其常见。
3. 负载均衡配置
多台后端服务器之间分发请求,需要借助balancer:
<Proxy balancer://mycluster>
BalancerMember http://192.168.1.11:8080 loadfactor=1
BalancerMember http://192.168.1.12:8080 loadfactor=1
BalancerMember http://192.168.1.13:8080 status=+H
</Proxy>
<VirtualHost *:80>
ServerName www.ipipp.com
ProxyPass / balancer://mycluster/
ProxyPassReverse / balancer://mycluster/
</VirtualHost>
loadfactor控制权重,status=+H表示该节点为热备(只有其他节点全挂了才启用)。如果需要会话保持,在ProxyPass后面加上stickysession=JSESSIONID参数,Apache会根据Cookie把同一用户的请求固定到同一台后端。
4. WebSocket代理
WebSocket使用Upgrade机制切换协议,普通的proxy_http模块处理不了,必须使用proxy_wstunnel模块:
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:3000/$1 [P,L]
ProxyPassReverse / ws://127.0.0.1:3000/
这里通过RewriteCond判断请求头中的Upgrade是否为websocket,是则用[P]标记代理到ws协议,否则走普通HTTP逻辑。别忘了加载mod_rewrite和mod_proxy_wstunnel两个模块。
三、HTTPS与超时等进阶参数
1. 代理后端HTTPS服务
如果后端本身是HTTPS,将目标地址写成https即可,同时建议关闭对自签证书的校验:
SSLProxyEngine On ProxyPass /app https://192.168.1.20:8443/app SSLProxyVerify none SSLProxyCheckPeerCN off SSLProxyCheckPeerName off ProxyPassReverse /app https://192.168.1.20:8443/app
如果不加SSLProxyVerify none,后端使用自签名证书时Apache会直接报502错误,日志里会出现certificate verification failed的字样。
2. 超时与连接池
后端接口较慢时,默认超时往往不够用,表现为页面返回502或504:
ProxyTimeout 300
<VirtualHost *:80>
ProxyPass / http://127.0.0.1:8080/ connectiontimeout=5 timeout=300 retry=30
</VirtualHost>
connectiontimeout是建立连接的超时,timeout是等待响应的超时,retry控制在后端故障后多久再尝试重连,默认60秒内即使后端恢复了也会直接返回503,调小这个值能让故障恢复更快生效。
四、常见错误与排查方法
1. ProxyPass指令无法识别,Apache启动失败
报错信息类似Invalid command 'ProxyPass',原因就是proxy相关模块没加载。解决方法是按前文方式启用模块后重启。如果模块已加载仍报错,检查是否把ProxyPass写在了错误的位置,该指令只能出现在VirtualHost、Location或服务器全局配置中,不能写在Directory块里。
2. 访问返回502 Bad Gateway
502意味着Apache连不上后端。排查步骤:先用curl http://127.0.0.1:8080在本机验证后端服务是否存活;检查SELinux是否拦截,CentOS下执行setsebool -P httpd_can_network_connect 1放行Apache的出站连接;查看错误日志/var/log/httpd/error_log中的具体原因。后端是HTTPS自签证书也会导致502,处理方式见上一节。
3. 访问返回503 Service Unavailable
多数情况是后端曾经宕机,Apache把节点标记为失败状态并在retry周期内拒绝转发。等retry时间过去,或者直接重启Apache清除状态即可。负载均衡场景下所有节点都不健康同样报503。
4. 请求头或真实IP丢失
后端拿到的客户端IP全是代理机器的IP。Apache默认会传递大部分头,但建议显式配置:
ProxyPreserveHost On
RequestHeader set X-Real-IP %{REMOTE_ADDR}s
RequestHeader set X-Forwarded-Proto %{REQUEST_SCHEME}s
后端应用再从X-Real-IP或X-Forwarded-For中解析真实客户端地址即可。注意负载均衡多级代理时,X-Forwarded-For会累积多个IP,取第一个才是最初的客户端。
5. Cookie路径错误导致登录态丢失
后端设置的Cookie如果path指向了内部路径,浏览器可能无法正确回传。可以在ProxyPassReverse后追加Cookie相关的path修改:
ProxyPassReverseCookiePath /internal /app ProxyPassReverseCookieDomain internal.ippipp.com www.ipipp.com
这两条指令分别改写Cookie的path和domain属性,使其与外部访问路径保持一致。
五、配置检查与上线建议
每次修改配置后先执行apachectl configtest验证语法,确认输出Syntax OK再重启服务,避免直接重启导致线上中断。日志排查时建议把LogLevel临时调到debug,可以看到mod_proxy每一次转发和响应的细节,问题定位效率会高很多。
整体来看,Apache反向代理的核心就是模块加载、ProxyPass与ProxyPassReverse的组合,再根据场景叠加负载均衡、WebSocket、超时等参数。把本文的示例和错误对照表过一遍,基本就能应对绝大多数代理需求了。
Apache反向代理proxy配置mod_proxy修改时间:2026-09-07 21:48:48