### 使用 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 將會自動檢測并重新標記它們的狀態)。

#### 工作原理
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
- 使用公共模塊
- 使用外部節點分類器
- 創建自定義的資源類型
- 創建自定義的提供者