代理方式有三种:正向代理、透明代理和反向代理
正向代理
httpd通过ProxyRequests指令配置正向代理的功能。例如:
ProxyRequests On ProxyVia On <Proxy "*"> Require host internal.example.com </Proxy>
其中< Proxy >容器表示的是只有internal.example.com下的主机可以通过该正向代理去访问任意URL的请求内容。ProxyVia指令表示在响应首部中添加一个Via字段。
反向代理
为了成为一个"基本的"web server,提供静态和动态内容给最终用户,httpd(以及其他大多数web server)可以扮演反向代理服务器的角色,也就是众所周知的"网关"服务器。
在这种场景下,Httpd自身不生成产出数据,而是从后端服务器中获取数据,这些后端服务器器一般不会和外界网络通信。当httpd从客户端接收到请求,请求被代理到后端服务器组中的其中一个服务器上,该后端服务器处理请求,生成内容并返回内容给httpd server,最后由httpd server生成实际的HTTP响应给客户端。
有无数应该使用反向代理的理由,最常见的是安全、高可用、负载均衡、集中授权/认证。反向代理的布置和架构中,后端服务器(真正处理请求的服务器)和外界完全绝缘并由此受到保护,对于外界客户端来说,当他们需要关心服务器对象是谁时,它们得到的结果总是反向代理服务器,而非后端服务器。
一个典型的实现如下:
简单的反向代理配置
ProxyPass指令用于映射请求到后端服务器。最简单的代理示例是对所有请求"/"都映射到一个后端服务器上:
ProxyPass "/" "http://www.example.com/" ProxyPassMatch "^/((?i).*\.php)$" "fcgi://127.0.0.1:9000/var/www/a.com/$1"
为了地址重定向时也能正确使用反向代理,应该使用ProxyPassReverse指令,该指令的作用见下文。
ProxyPass "/" "http://www.example.com/" ProxyPassReverse "/" "http://www.example.com/"
或者只为特定的URI进行代理,例如下面的配置,只有/images开头的路径才会代理转发,其他的所有请求都在本地处理。
ProxyPass "/images" "http://www.example.com/" ProxyPassReverse "/images" "http://www.example.com/"
假如本地服务器地址为http://www1.example.com
,当请求http://www1.example.com/images/a.gif
时,将代理为http://www.example.com/a.gif
。
在没有重定向的情况下,ProxyPassReverse是可以省略的,否则一般情况下应该将其设置为和ProxyPass相同。ProxyPassReverse提供的是一种功能,它并不依赖于ProxyPass(但一般都同时存在)。它的作用是防止重定向时客户端无法正确访问。例如,http://www.example.com/images/a.gif
被代理为http://192.168.100.17/a.gif
,如果此时a.gif被重定向到b.gif,那么代理服务器返回给客户端的将是http://192.168.100.17/b.gif
。但客户端是无法访问后端内网主机192.168.100.17的,于是出现file not found错误。如果此时使用ProxyPassReverse,那么代理服务器响应给客户端的请求会被调整为http://www.example.com/images/b.gif
,这样的请求再发给代理服务器,就能正确访问。
负载均衡:后端成员
上面的配置中没有添加后端服务器节点,无法享受反向代理的优点。因此,有必要添加后端节点。添加的方法是使用< proxy >容器将后端节点定义成一个负载均衡组,各节点是该组中成员,然后代理目标指向组名即可。
例如:
<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/"
alancer://myset告诉httpd,它创建了一个负载均衡节点集合,名称为myset,此集合中有两个后端成员。在上面的配置中,任意/images的请求都会代理至2个成员中的一个。ProxySet指令指定myset均衡组使用的均衡算法为bytraffic,即基于I/O流量字节数权重的算法。ProxySet指令设置的是Proxy容器的公共属性。
httpd有3种负载均衡算法:
- byrequests:默认。基于请求数量计算权重。
- bytraffic:基于I/O流量大小计算权重。
- bybusyness:基于挂起的请求(排队暂未处理)数量计算权重。
对于上面的示例,还可以稍加修改,使其支持更多功能。例如添加权重比例,使得某后端节点被转发到的权重是另一节点的3倍,等待后端节点返回数据的超时时间为1秒。
<Proxy balancer://myset> BalancerMember http://www2.example.com:8080 BalancerMember http://www3.example.com:8080 loadfactor=3 timeout=1 ProxySet lbmethod=byrequests </Proxy> ProxyPass "/images" "balancer://myset/" ProxyPassReverse "/images" "balancer://myset/"
故障转移
还可以再次调整实现故障转移,例如当所有负载节点都失败时,指定一个备份节点(standby node)。参考如下配置:
<Proxy balancer://myset> BalancerMember http://www2.example.com:8080 BalancerMember http://www3.example.com:8080 loadfactor=3 timeout=1 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/"
其中成员1、2、4、5是负载节点,成员3是备份节点。当所有负载节点都不健康时,将转发请求给备份节点,并由备份节点处理请求,httpd设置备份节点的方式很简单,只需将状态设置为"H",表示hot-standby。还需注意的是负载节点4、5,它们额外的参数为lbset=1,不写时默认为0,这是负载均衡时的优先级设置,负载均衡时总是先转发给低数值的节点,也就是说数值越小,优先级越高。所以上面的配置中,当节点1、2正常工作时,只在它们之间进行负载,此时节点4、5处于闲置状态。只有当节点1、2都失败时,才会在节点4、5之间进行负载。
提供负载状态显示页面
<Location "/bm"> SetHandler balancer-manager Require host localhost Require ip 192.168.100 </Location>
然后在浏览器中输入http://server/bm即可,返回结果如图。
proxy相关指令
ProxyPass指令
该指令将远程服务器映射到本地主机上,但本地主机不是真实的服务器,而是远程主机的一个镜像。这个镜像通常称为反向代理服务器或网关。该指令不能用于< Directory >、< Files >容器中,且使用该指令时通常会关闭正向代理,即ProxyRequests=off
。