使用 HAProxy 为多个 web 服务器实现负载均衡
The inside of a computer is as dumb as hell but it goes like mad!
— Richard Feynman
曾几何时,为缓慢的 Web 服务器加速的方式就是增加更多的 CPU 核心。 我记得一个老板买了一台 24核的 Sun 工作站,它是个尺寸接近悍马的怪物, 以至于我们不得不扩修数据中心的大门才能将其放入。
时至今日,扩展 Web 站点规模仍旧是添加 CPU 核心的问题,但与从前不同的是: 要么他们自己拿来若干粉色的 PC 机作为服务器使用; 要么从云服务提供商那里租用服务器作为计算资源使用。 为了对所有这些核心进行分组,从而一起服务于单一的 Web 站点, 我们要使用负载均衡器(load balancer)。
曾经,负载均衡器是坐落在机架上的一个耗资八万美元的大盒子。 尽管你现在仍旧可以购买这种负载均衡器,但对于大多数组织来说, 使用 Linux 商品服务器的软件负载均衡解决方案可以大大削减成本。
对大多数管理员来说,HAProxy 是软件负载均衡器的一种选择:快速、强大、高度可配置。 在下面的处方中,将向你展示如何创建一个 HAProxy 服务器为两个现有的后端服务器实现对其 web 请求的负载均衡。
操作步骤
创建 loadbalancer 模块:
# mkdir /etc/puppet/modules/loadbalancer # mkdir /etc/puppet/modules/loadbalancer/manifests # mkdir /etc/puppet/modules/loadbalancer/files
使用如下内容创建 /etc/puppet/modules/loadbalancer/manifests/init.pp 文件:
class loadbalancer { package { "haproxy": ensure => installed } file { "/etc/default/haproxy": source => "puppet:///modules/loadbalancer/haproxy.defaults", require => Package["haproxy"], } service { "haproxy": ensure => running, enable => true, require => Package["haproxy"], } file { "/etc/haproxy/haproxy.cfg": source => "puppet:///modules/loadbalancer/haproxy.cfg", require => Package["haproxy"], notify => Service["haproxy"], } }
使用如下内容创建 /etc/puppet/modules/loadbalancer/files/haproxy.defaults 文件:
# Don't edit this file - it's managed by Puppet # Set ENABLED to 1 if you want the init script to start haproxy. ENABLED=1 # Add extra flags here. #EXTRAOPTS="-de -m 16"
使用如下内容创建 /etc/puppet/modules/loadbalancer/files/haproxy.cfg 文件。 在 myapp 部分中,用你的后端服务器 IP 地址替换每个 server 行中的 IP 地址, 并用你的后端服务器监听端口替换端口 :8000。
global daemon user haproxy group haproxy pidfile /var/run/haproxy.pid defaults log global stats enable mode http option httplog option dontlognull option dontlog-normal retries 3 option redispatch contimeout 4000 clitimeout 60000 srvtimeout 30000 listen stats :8080 mode http stats uri / stats auth haproxy:topsecret listen myapp 0.0.0.0:80 balance leastconn server myapp1 10.0.2.30:8000 check maxconn 100 server myapp2 10.0.2.40:8000 check maxconn 100
在你的 HAProxy 节点中包含如下代码:
include loadbalancer
运行 Puppet:
# puppet agent --test info: Retrieving plugin info: Caching catalog for cookbook.bitfieldconsulting.com info: Applying configuration version '1311616315' notice: /Stage[main]/Loadbalancer/Package[haproxy]/ensure: ensure changed 'purged' to 'present' --- /etc/haproxy/haproxy.cfg 2009-11-06 17:59:44.000000000 +0000 +++ /tmp/puppet-file20110725-16369-1b85cr8-0 2011-07-25 18:09:03.749146699 +0000 @@ -1,86 +1,28 @@ -# this config needs haproxy-1.1.28 or haproxy-1.2.1 ... info: /Stage[main]/Loadbalancer/File[/etc/haproxy/haproxy. cfg]: Filebucketed /etc/haproxy/haproxy.cfg to puppet with sum c3bfb0c86138552475dea458e8ab36f3 notice: /Stage[main]/Loadbalancer/File[/etc/haproxy/haproxy.cfg]/ content: content changed '{md5}c3bfb0c86138552475dea458e8ab36f3' to '{md5}fa5fac3cf31f043f0120d0d45cef3f54' info: /Stage[main]/Loadbalancer/File[/etc/haproxy/haproxy.cfg]: Scheduling refresh of Service[haproxy] notice: /Stage[main]/Loadbalancer/Service[haproxy]/ensure: ensure changed 'stopped' to 'running' notice: /Stage[main]/Loadbalancer/Service[haproxy]: Triggered 'refresh' from 1 events --- /etc/default/haproxy 2009-11-06 17:59:21.000000000 +0000 +++ /tmp/puppet-file20110725-16369-1ndfrti-0 2011-07-25 18:09:05.749136866 +0000 @@ -1,4 +1,5 @@ # Set ENABLED to 1 if you want the init script to start haproxy. -ENABLED=0 +ENABLED=1 # Add extra flags here. #EXTRAOPTS="-de -m 16" + notice: /Stage[main]/Loadbalancer/File[/etc/default/haproxy]/ content: content changed '{md5}a1f2deb7c7a10e55dc7c971a2288f5d4' to '{md5}2217d74d66bd72630268598b1f11f173' notice: Finished catalog run in 22.21 seconds
在你的浏览器中检查 HAProxy 的 stats 界面确保一切工作正常(注意我的 Backend 服务器显示的是 DOWN ,因为这些虚拟机还没有运行。当我启动它们之后,HAProxy 将会自动检测并重新标记它们的状态)。
工作原理
haproxy 守护进程监听进入的请求并将其分发到一组后端服务器(本例中是 myapp1 和 myapp2)。 如果一个后端服务器已超载,HAProxy 将避免向其发送更多的流量直至它恢复。 这有助于防止单台 Web 服务器因为超载(排队等待的不能被处理的请求越来越多)而造成的响应速度大幅放缓。 如果一台后端服务器宕机,HAProxy 将不会为其分发任何请求,直至其重新可用。
stats 界面会显示:你的后端服务器如何执行,有多少会话正在处理, HAProxy 是否将后端服务器标记成了 UP 或 DOWN,等信息。
更多用法
如果你想添加更多的后端服务器以处理不断增长的需求,只需在 haproxy.cfg 中添加更多的 server 行。 如果你发现现有的后端服务器响应速度越来越慢,请适当减少每个服务器的 maxconn 值。 HAProxy 有大量值得探索的配置参数,参考 HAProxy 的文档站点 http://haproxy.1wt.eu/#docs 。
如果你需要提供 SSL 的能力,可以将 Nginx 放在 HAProxy 的前端进行处理。
尽管 HAProxy 经常用于 Web 服务器,但它可以代理很多服务,不仅仅是 HTTP。 它可以处理任何 TCP 流量,所以你可以使用 HAProxy 为 MySQL 服务器、SMTP 服务器、 视频服务器以及任何你想要的服务器实现负载均衡。