Apache 反向代理指南

除了做为基本的网页服务器,提供静态和动态内容给终端用户以外,Apache 也可以扮演反向代理服务器,也称网关服务器。

在这种情况下,httpd 自己不会生成数据,也不会提供数据,其内容都是从一个或多个后端服务器获得的。这些后端服务器通常不会直接连到外界网络。当 httpd 从客户端收到一个请求时,该请求被代理到其中一台后端服务器,然后由它处理该请求,生成内容,并把内容返回给 httpd,由 httpd 负责为客户端生成真正的 HTTP 应答。

这种方案的部署有很多考量,但通常是考虑到安全、高可用、负载平衡、集中验证、集中授权。在该方案中,有一点非常重要,即将后端设施的布局、设计和架构与外界隔离,保护起来。对于客户端来说,所有的内容来源只是反向代理服务器。

image-center

反向代理

相关模块 相关指令
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 重定向应答中 LocationContent-LocationURI 标头中的 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/"

失效切换

可以对失效切换的细节进行微调,哪种情况下应该访问哪个成员,甚至哪个均衡器。

以下范例设置三个失效切换:

  1. 只有在 http://www2.example.com:8080http://www3.example.com:8080 其中的一个或全部变成不可用时,才使用 http://spare1.example.com:8080http://spare2.example.com:8080 来发送流量。一个 spare 替换一个同组均衡器中失效的成员。
  2. 只有在均衡器 0 中所有其它 workers 都不可用时,才使用 http://hstandby.example.com:8080 发送流量。
  3. 如果均衡器中所有 workers、spares、standby 都不可用,才用均衡器 1 中的 http://bkup1.example.com:8080http://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 的管理页面。

image-center

动态健康检查

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 的动态健康检查失败 ,直到通过后续检查才能使用

##