### 使用 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 请求的负载均衡。
#### 操作步骤
1. 创建 loadbalancer 模块:
```
# mkdir /etc/puppet/modules/loadbalancer
# mkdir /etc/puppet/modules/loadbalancer/manifests
# mkdir /etc/puppet/modules/loadbalancer/files
```
2. 使用如下内容创建 /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"],
}
}
```
3. 使用如下内容创建 /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"
```
4. 使用如下内容创建 /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
```
5. 在你的 HAProxy 节点中包含如下代码:
```
include loadbalancer
```
6. 运行 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
```
7. 在你的浏览器中检查 HAProxy 的 **stats** 界面确保一切工作正常(注意我的 **Backend** 服务器显示的是 **DOWN** ,因为这些虚拟机还没有运行。当我启动它们之后,HAProxy 将会自动检测并重新标记它们的状态)。
![https://box.kancloud.cn/2016-05-12_5733eeecc4ce5.png](https://box.kancloud.cn/2016-05-12_5733eeecc4ce5.png)
#### 工作原理
haproxy 守护进程监听进入的请求并将其分发到一组后端服务器(本例中是 **myapp1** 和 **myapp2**)。 如果一个后端服务器已超载,HAProxy 将避免向其发送更多的流量直至它恢复。 这有助于防止单台 Web 服务器因为超载(排队等待的不能被处理的请求越来越多)而造成的响应速度大幅放缓。 如果一台后端服务器宕机,HAProxy 将不会为其分发任何请求,直至其重新可用。
**stats** 界面会显示:你的后端服务器如何执行,有多少会话正在处理, HAProxy 是否将后端服务器标记成了 **UP** 或 **DOWN**,等信息。
#### 更多用法
如果你想添加更多的后端服务器以处理不断增长的需求,只需在 haproxy.cfg 中添加更多的 server 行。 如果你发现现有的后端服务器响应速度越来越慢,请适当减少每个服务器的 maxconn 值。 HAProxy 有大量值得探索的配置参数,参考 HAProxy 的文档站点 [http://haproxy.1wt.eu/#docs](http://haproxy.1wt.eu/#docs) 。
如果你需要提供 SSL 的能力,可以将 Nginx 放在 HAProxy 的前端进行处理。
尽管 HAProxy 经常用于 Web 服务器,但它可以代理很多服务,不仅仅是 HTTP。 它可以处理任何 TCP 流量,所以你可以使用 HAProxy 为 MySQL 服务器、SMTP 服务器、 视频服务器以及任何你想要的服务器实现负载均衡。
- Puppet 2.7 Cookbook 中文版
- 中文翻译版
- 译者序
- 项目缘起
- 翻译方法
- 社区链接
- 社区建议
- 贡献者
- 原书版权页
- 关于作者
- 前言
- 本书内容
- 阅读前提
- 适用读者
- 格式约定
- 读者反馈
- 客户支持
- 下载案例代码
- 勘误表
- Puppet 基础设施
- 使用版本控制
- 使用提交钩子
- 使用 Rake 部署变更
- 配置 Puppet 的文件服务器
- 从 cron 运行 Puppet
- 使用自动签名
- 预签名证书
- 从 Puppet 的 filebucket 检索文件
- 使用 Passenger 扩展 Puppet 的部署规模
- 创建去中心化的分布式 Puppet 架构
- 监控、报告和排错
- 生成报告
- 通过 Email 发送包含特定标签的日志信息
- 创建图形化报告
- 自动生成 HTML 文档
- 绘制依赖关系图
- 测试你的 Puppet 配置清单
- 执行模拟运行
- 检测编译错误
- 理解 Puppet 的错误信息
- 显示命令的输出结果
- 输出调试信息
- 检查配置设置
- 使用标签
- 使用运行阶段
- 使用不同的环境
- Puppet 语言及其写作风格
- 使用 Puppet 社区规范
- 使用模块
- 使用标准的命名规范
- 使用嵌入式 Ruby 代码
- 使用纯 Ruby 代码书写配置清单
- 遍历多个项目
- 书写强大的条件语句
- 在 if 语句中使用正则表达式
- 使用选择器和 case 语句
- 检测字符串中是否包含指定的值
- 使用正则表达式替换
- 书写更优质的配置清单
- 使用资源的数组
- 使用 define 资源
- 指定资源的依赖关系
- 使用节点继承
- 使用类的继承和重载
- 给类传递参数
- 书写可重用的跨平台配置清单
- 获得系统的环境信息
- 导入动态信息
- 从 CSV 文件导入数据
- 给 Shell 命令传递参数
- 使用文件和软件包
- 为配置文件添加配置行
- 使用 Augeas 自动修改配置文件
- 使用配置片段构建配置文件
- 使用 ERB 模板
- 在模板中遍历数组
- 从第三方仓库安装软件包
- 配置 APT 软件仓库
- 配置 GEM 仓库
- 从源码包自动构建软件
- 比较软件包的版本
- 用户和虚拟资源
- 使用虚拟资源
- 使用虚拟资源管理用户
- 管理用户基于密钥的 SSH 访问
- 管理用户的自定义文件
- 有效地分发 cron 任务
- 当文件更新时运行命令
- 使用主机资源
- 为文件资源指定多个源
- 使用文件资源递归地分发整个目录树
- 清理过期的旧文件
- 使用日程表资源
- 资源的审计
- 临时禁用资源
- 管理时区
- 应用程序
- 管理 Apache 服务
- 创建 Apache 虚拟主机
- 创建 Nginx 虚拟主机
- 创建 MySQL 数据库及用户
- 管理 Drupal 站点
- 管理 Rails 应用程序
- 服务器和云基础设施
- 部署 Nagios 监控服务器
- 使用 Heartbeat 构建高可用服务
- 管理 NFS 服务和文件共享
- 使用 HAProxy 为多个 web 服务器实现负载均衡
- 使用 iptables 管理防火墙
- 管理 Amazon 的 EC2 实例
- 使用 Vagrant 管理虚拟机
- 外部工具和 Puppet 生态环境
- 创建 Facter 的自定义 fact
- 在运行 Puppet 之前和之后执行命令
- 从 Shell 会话生成 Puppet 配置清单
- 从运行的系统上生成 Puppet 配置清单
- 使用 Puppet Dashboard
- 使用 Foreman
- 使用 MCollective
- 使用公共模块
- 使用外部节点分类器
- 创建自定义的资源类型
- 创建自定义的提供者