Apache 反向代理指南
除了做为基本的网页服务器,提供静态和动态内容给终端用户以外,Apache 也可以扮演反向代理服务器,也称网关服务器。
在这种情况下,httpd 自己不会生成数据,也不会提供数据,其内容都是从一个或多个后端服务器获得的。这些后端服务器通常不会直接连到外界网络。当 httpd 从客户端收到一个请求时,该请求被代理到其中一台后端服务器,然后由它处理该请求,生成内容,并把内容返回给 httpd,由 httpd 负责为客户端生成真正的 HTTP 应答。
这种方案的部署有很多考量,但通常是考虑到安全、高可用、负载平衡、集中验证、集中授权。在该方案中,有一点非常重要,即将后端设施的布局、设计和架构与外界隔离,保护起来。对于客户端来说,所有的内容来源只是反向代理服务器。

反向代理
| 相关模块 | 相关指令 |
|---|---|
| mod_proxy | ProxyPass |
| mod_proxy_balancer | BalancerMember |
| mod_proxy_hcheck |
简易反向代理
代理所有地址
ProxyPass 指令用于设定传入请求到后端服务器的映射。最简单的范例是把所有请求代理到后端:
ProxyPass "/" "http://www.example.com/"
所有请求用 "/" 表示。
替换标头信息
另外,为了确保后端生成的标头信息中的 Location: 会被替换,而指向反向代理,而不是指向后端服务器本身,则必须使用 ProxyPassReverse 指令:
ProxyPass "/" "http://www.example.com/"
ProxyPassReverse "/" "http://www.example.com/"
ProxyPassReverse 指令会让 Apache 调整 HTTP 重定向应答中 Location、Content-Location、URI 标头中的 URL,这样可以避免出现 “重定向到后端服务器导致反向代理被绕过的” 问题。
代理特定地址
如果仅代理特定的地址,可以如下:
ProxyPass "/images" "http://www.example.com/"
ProxyPassReverse "/images" "http://www.example.com/"
只有 /images 开头的网址才会被代理到指定后端,否则本地处理。
集群与均衡器
虽然反向代理很有用,但依然会存在后端服务器负载过重,有当机的危险。真正需要的是定义一组后端服务器来处理所有的请求,使用反向代理来做负载均衡及失效切换。这组后端服务器称为集群(cluster),但 Apache 称之为均衡器(balancer)。可以用 <Proxy> 和 BalancerMember 语句来定义:
<Proxy balancer://myset>
BalancerMember http://www2.example.com:8080
BalancerMember http://www3.example.com:8080
ProxySet lbmethod=bytraffic
</Proxy>
ProxyPass "/images/" "balancer://myset/"
ProxyPassReverse "/images/" "balancer://myset/"
balancer:// 语法用于告知 httpd 我们正在创建一组均衡器,名字为 myset。它包含 2 个后端服务器,httpd 称之为均衡器成员(BalancerMembers)。本例中,所有对 /images 的请求都会被代理到这两个后端之一的服务器上。ProxySet 指令用于设定 myset 均衡器的均衡机制,基于 I/O 字节数。
均衡器成员有时也称为 workers,工人。
均衡器与成员的配置
通过 ProxyPass 中定义的参数,可以调整均衡器与成员的各种配置细节。
例如,假设我们希望 http://www3.example.com:808 来接管 3 倍的流量,超时为 1 秒:
<Proxy balancer://myset>
BalancerMember http://www2.example.com:8080
BalancerMember http://www3.example.com:8080 loadfactor=3 timeout=1
ProxySet lbmethod=bytraffic
</Proxy>
ProxyPass "/images" "balancer://myset/"
ProxyPassReverse "/images" "balancer://myset/"
失效切换
可以对失效切换的细节进行微调,哪种情况下应该访问哪个成员,甚至哪个均衡器。
以下范例设置三个失效切换:
- 只有在
http://www2.example.com:8080与http://www3.example.com:8080其中的一个或全部变成不可用时,才使用http://spare1.example.com:8080和http://spare2.example.com:8080来发送流量。一个 spare 替换一个同组均衡器中失效的成员。 - 只有在均衡器 0 中所有其它 workers 都不可用时,才使用
http://hstandby.example.com:8080发送流量。 - 如果均衡器中所有 workers、spares、standby 都不可用,才用均衡器 1 中的
http://bkup1.example.com:8080和http://bkup2.example.com:8080来轮换。
因此,每个负载均衡器都可以有一个或多个 hot spares 和 hot standbys。
<Proxy balancer://myset>
BalancerMember http://www2.example.com:8080
BalancerMember http://www3.example.com:8080 loadfactor=3 timeout=1
BalancerMember http://spare1.example.com:8080 status=+R
BalancerMember http://spare2.example.com:8080 status=+R
BalancerMember http://hstandby.example.com:8080 status=+H
BalancerMember http://bkup1.example.com:8080 lbset=1
BalancerMember http://bkup2.example.com:8080 lbset=1
ProxySet lbmethod=byrequests
</Proxy>
ProxyPass "/images/" "balancer://myset/"
ProxyPassReverse "/images/" "balancer://myset/"
对于失效切换来说,hot spare 用于替换同组均衡器中不可用的 worker。如果 worker 资源耗尽、停止运行了,或发生错误,进行失效状态,它就变得不可用。如果均衡器中所有 worker 和 spare 都不可用了,才使用 hot standby。
Balancer Manager 程序
Apache 反向代理最独特、最有用的功能之一是嵌入的 balancer-manager 程序。与 mod_status 类似,balancer-manager 会当前工作的配置信息,以及启用的均衡器及 workers 的状态信息。除此之外,还可以在运行时对均衡器及 worker 进行动态实时的重配置,包括向均衡器添加新成员。要想实现这些功能,需要向配置文件中添加以下内容:
<Location "/balancer-manager">
SetHandler balancer-manager
Require host localhost
</Location>
必须首先配置好服务器的访问控制,然后才启用 balancer-manager,尤其要严格限制对 URL 的访问。通过 <Proxy> 指令来严格控制哪些地址可以访问代理服务器:
<Proxy "*">
Require ip 192.168.0
</Proxy>
当客户端访问 http://rproxy.example.com/balancer-manager/ 时,会进入 balancer-manager 的管理页面。

动态健康检查
httpd 在把请求代理给 worker 之前,它可以先测试一下,看 worker 是否可用。通过用 ProxyPass 给该 worker 设置 ping 参数来实现。
通常情况下,用一种动态的方式检查工人的健康状况会更有用,由 mod_proxy_hcheck 模块来完成。
均衡器成员状态标签
在 balancer-manager 管理页面中,会显示 worker 的当前状态,可以在界面中进行设置或重置,这些状态标签的含义如下:
| 标签 | 字符串 | 说明 |
|---|---|---|
| Ok | worker 可用 | |
| Init | worker 已初始化 | |
| D | Dis | worker 被禁用,不会接受任何请求,会自动重试 |
| S | Stop | worker 出于管理目的被停止,不会接受任何请求,不会自动重试 |
| I | Ign | worker 处于忽略错误模式,将始终被视为可用 |
| R | Spar | worker 为 hot spare |
| H | Stby | worker 处于 hot standby 模式 |
| E | Err | worker 处于错误状态,通常由预请求检查失败引起。请求不会代理到该 worker,但根据其 retry 设置也许会重试 |
| N | Drn | worker 处于 drain 模式,只接受现有的指向自己的 sticky 会话,会忽略所有其它请求 |
| C | HcFl | worker 的动态健康检查失败 ,直到通过后续检查才能使用 |
##