文章内容参考自官方文档: http://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
像nginx一样, Apache httpd也提供了反向代理(Reverse Proxy)并能实现负载均衡(Load Balance)。
Apache httpd配置中需要开启以下模块:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_http_module modules/mod_proxy_http.so
# 这个也要开启, 否则httpd启动报错
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
# 以下负载均衡策略按需开启
LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
linux下可以开启
mod_proxy_hcheck.so
以检查成员存活状态 (动态健康检查)
mod_lbmethod 模块按需开启, 如果只需按流量则开启mod_lbmethod_bytraffic.so即可
mod_proxy 提供代理功能,mod_proxy_balancer 提供负载均衡功能, mod_proxy_http 让代理服务器能支持HTTP协议。
需要用到的指令: ProxyPass
, ProxyPassReverse
, BalancerMember
实现简单的反向代理 (Simple reverse proxying)
指令ProxyPass
把输入请求映射到后端服务器(或者服务器集群)。先看一个最简单的把所有请求(“/”) 都反向代理到一台服务器的例子:
ProxyPass "/" "http://www.example.com/"
为了确保从后端服务器生成的“Location”头部被修改以指向反向代理,而不是回到自身(形成死循环),需要添加ProxyPassReverse指令:
ProxyPass "/" "http://www.example.com/"
ProxyPassReverse "/" "http://www.example.com/"
如果要设置指定的url被反向代理, 按如下设置:
ProxyPass "/images" "http://www.example.com/"
ProxyPassReverse "/images" "http://www.example.com/"
上面的例子, 把所有以"/images"开头的请求代理到指定的后端, 其他请求都被本地处理.
ProxyPass "/" "http://www.example.com/"
集群和均衡器 (Clusters and Balancers)
通过balancer://
来设置一个均衡器, 来把请求反向代理到多个后端服务器。
<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/"
上面的代码把以“/images/”开头的请求代理到以BalancerMembers
定义的2台后端服务器, 用ProxySet
来定义负载均衡策略。
均衡器成员(BalancerMembers)有时也被称为节点(workers).
均衡器和成员配置 (Balancer and BalancerMember configuration)
默认是平均分配负载, 如果需要指定, 可以设置负载因子(loadfactor
)。
<Proxy balancer://myset>
BalancerMember http://www2.example.com:8080 loadfactor=8
BalancerMember http://www3.example.com:8080 loadfactor=2
ProxySet lbmethod=bytraffic
</Proxy>
ProxyPass "/images/" "balancer://myset/"
ProxyPassReverse "/images/" "balancer://myset/"
上面设置了2台服务器,并且把负载分配比例设置为8:2。 如果不设置loadfactor则默认是1。
如果要设置www3的负载是www2的两倍且超时时间1s, 可以如下设置:
<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/"
故障转移 (Failover)
您还可以微调各种故障转移方案,详细说明在这种情况下应访问哪些节点甚至哪些均衡器。下面的设置实现了三种故障转移情况:
<Proxy balancer://myset>
BalancerMember http://www2.example.com:8080 loadfactor=7
BalancerMember http://www3.example.com:8080 loadfactor=3
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/"
- 当 www3和www2中的一个或者两个都不可用的时候, 会把流量分配给冗余端 spare1和spare2。(一个冗余端会被用来替换本均衡器的一个不可用的成员。)
- 当所有的lbset=0的节点(worker)不可用时, 才会把流量分配给 hstandby (热备机)。
- 如果所有的lbset=0的节点、冗余和热备都不可用, 当且仅当此时, blset=1的备份机器 bkup1和bkup2 才会进入循环(分配到流量)。
每个均衡器设置可以用一个或多个冗余(hot spares)和热备份(hot standbys)成员。
对于故障转移,冗余(spare)用来替换同一个负载均衡器里面的不可用的节点。 如果节点正在耗尽,停止或处于错误/失败状态,则认为该节点不可用。 如果负载均衡器集中的所有节点和冗余(spare)都不可用,则启用热备用。 始终按从最低到最高的顺序尝试负载均衡器集(及各自的冗余和热备)。
均衡器的管理 (Balancer Manager)
Apache内置的 balancer-manager
可以显示当前的配置及工作状态。不但可以显示参数, 还可以动态的,在运行时重新配置大多数参数, 包括添加新的成员到已存在的均衡器中。
在Apache httpd配置文件中添加:
<Location "/balancer-manager">
SetHandler balancer-manager
Require host localhost
</Location>
注意: 生产服务器中不可开启, 除非你已经进行了安全设置。
重启httpd后访问 http://yourdomain/balancer-manager/ :
经过测试:
balancer-manager
只能放在配置文件httpd.conf下才有效, 放在VirtualHost中无效.
动态健康检查 (Dynamic Health Check)
在httpd反向代理向节点发出请求之前,它可以通过使用ProxyPass为该节点设置参数ping来“测试”该节点是否可用。 通常,以动态方式带外(out of band)检查节点的健康状况更有用。 这是通过Apache httpd的mod_proxy_hcheck模块实现的。
实战操作
前面在配置文件 httpd.conf 中设置反向代理, 会影响到整个服务器上的站点。如果一个服务器上有多个站点(域名), 需要指定某些域名才使用反向代理时,把配置转移到 VirtualHost 中即可(同时取消httpd.conf中的balancer设置)。
现在我们在本机的apache服务下直接做负载均衡测试。
在httpd-vhost.conf中添加以下配置:
<VirtualHost *:80>
ServerAdmin aben_sky@qq.com
ServerName www.example.com
ErrorLog "d:/wamp/logs/www.example.com.log"
CustomLog "d:/wamp/logs/www.example.com.log" combined
#Load Balance===========================
#关闭正向代理 ProxyRequests
ProxyRequests Off
<Proxy balancer://myset>
BalancerMember http://www2.example.com loadfactor=5
BalancerMember http://www3.example.com loadfactor=5
ProxySet lbmethod=bytraffic
</Proxy>
ProxyPass "/" "balancer://myset/"
ProxyPassReverse "/" "balancer://myset/"
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "E:/WWW/example.com/www2/"
ServerName www2.example.com
ErrorLog "d:/wamp/logs/www.example.com.log"
CustomLog "d:/wamp/logs/www.example.com.log" combined
<Directory "E:/WWW/example.com/www2/">
Options FollowSymLinks
AllowOverRide all
Order Deny,Allow
Allow from all
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "E:/WWW/example.com/www3/"
ServerName www3.example.com
ErrorLog "d:/wamp/logs/www.example.com.log"
CustomLog "d:/wamp/logs/www.example.com.log" combined
<Directory "E:/WWW/example.com/www3/">
Options FollowSymLinks
AllowOverRide all
Order Deny,Allow
Allow from all
Require all granted
</Directory>
</VirtualHost>
上面建立了3个站点: www, www2, www3。其中www作为负载均衡的控制端, www2和www3是实际的网站。我们在www2和www3的入口文件夹下建立一个index.php文件, 内容如下:
<?php
session_start();
echo date('Y-m-d H:i:s').'<br/>';
echo $_SERVER['HTTP_HOST'].'<br/>';
var_dump($_SERVER);
然后在本机hosts中添加域名解析, 然后访问 http://www.example.com看看:
这就完成了一个简单的负载均衡服务的搭建。
注意看下$_SERVER中多了HTTP_X_FORWARDED_HOST
和HTTP_X_FORWARDED_SERVER
:
["HTTP_X_FORWARDED_HOST"]=>string(15) "www.example.com"
["HTTP_X_FORWARDED_SERVER"]=>string(15) "www.example.com"
如果BalancerMember分布在不同的服务器上, 需要进行session的同步, 可以使用文件夹同步、保存到memcache/redis中的方式来实现。
来源:oschina
链接:https://my.oschina.net/abensky/blog/4310452