富人用 L4 Switch,窮人用 Linux HAProxy : )
關於負載平衡(Load Balance)
現在很多網絡服務都需要服務大量使用者,以前可以花費金錢擴充電腦硬件設施,但隨著網絡服務的用量增加,增加伺服器硬件設備已經無法解決問題。為了可以擴充服務,負載平衡成為主流的技術,雖然這幾年雲端與分散式儲存運算技術十分流行,但除非有特別的使用需求,不然在技術上,Load Balancing 是比較容易達成與掌握的技術。負載平衡除了分流能力之外,另一個很大的好處就是可以提供 High Availability,也就是傳說中的 HA 架構,即是一部電腦不能運作,而其他的電腦也可以繼續服務,降低斷線率。
目前還有很多大型網站都是使用典型的 Load Balance 架構,就像下圖由一部 Switch 或 Proxy 接收來自 Internet 的連線請求,然後分散給後端的 Cluster Server,藉此提高處理的連線量。除了上述的典型架構之外,也可透過 DNS 的配合來分散流量,整體來說還算是良好的管理架構。
這裡的典型架構最重要的就是 Load Balance 這部前端的 Gateway,如果購買 L4/L7 Switch 就需要大量金錢,設定也相當複雜。還好 Open Source的力量極大,可以使用 HAProxy,現就介紹如何使用。
Linux 安裝 HAProxy
以下介紹「套件安裝」與「編譯安裝」兩種安裝方式,由於稍等我們會介紹到如何設定 SSL 連線,因此請務必安裝 1.5 以上的版本(SSL 是 1.5 之後才提供的 Feature)。
套件安裝
Debian 可透過 apt 直接安裝,以下例子是在 Ubuntu Server 環境中操作
sudo apt-get install software-properties-common python-software-properties
sudo apt-add-repository ppa:vbernat/haproxy-1.5
sudo apt-get update
sudo apt-get install haproxy
編譯安裝 (RedHat或CentOS皆適用)
請到「HAProxy 官方網站」下載 Source Code 並解壓縮,以下範例版本是 1.5.3。
wget http://www.haproxy.org/download/1.5/src/haproxy-1.5.3.tar.gz
tar -zxvf haproxy-1.5.3.tar.gz
cd haproxy-1.5.3/
開始編譯 HAProxy,假設 linux 核心為 2.6.x,可以用使用 TARGET=linux26 的參數進行最佳化,如果真的不知道可以用 TARGET=generic 即可,如下:
make clean
make TARGET=linux26 USE_OPENSSL=1 ADDLIB=-lz
sudo make PREFIX=/usr/local/haprox
設定HAProxy
修改設定檔/etc/haproxy/haproxy.cfg(如果是編譯安裝會在/etc/haproxy.cfg),設定如下:
global
log /dev/log local0
log /dev/log local1 notice
maxconn 1024
user haproxy
group haproxy
daemon
nbproc 1
pidfile /var/run/haproxy.pid
tune.ssl.default-dh-param 1024
defaults
log global
mode http
option httplog
option dontlognull
#以下幾個Timeout設定要跟後端的PHP配合調整
timeout server 30s
timeout connect 30s
timeout client 30s
#如果伺服器不能運作時需retry的次數
retries 2
#Web服務入口
frontend switch
bind *:80
mode http
option httpclose
option forwardfor
reqadd X-Forwarded-Proto:\ https
default_backend web_server_cluster
#HAProxy 監控儀表板
listen stats :8080
mode http
stats enable
stats hide-version
stats realm Haproxy\ Statistics
stats uri /
#帳號密碼
stats auth your_username:your_password
stats refresh 10s
#設定Web Cluster
backend web_server_cluster
mode http
balance roundrobin
cookie SERVERID insert indirect nocache
# Web Server Cluster
server web1 192.168.1.10:80 check cookie s1
server web2 192.168.1.11:80 check cookie s2
重啟 HAProxy 載入設定
sudo service haproxy restart
使用瀏覽器連線後,HAProxy 就會自動分派 HTTP Request 到後端的電腦中,上述設定檔有一個「cookie SERVERID insert indirect nocache」是用來記錄連線的伺服器位置,這個功能相當不錯。可以讓某個瀏覽器發出的 Request 統一導向同一部電腦,避免一些資料交換的問題。可以偷看一下Chrome 收到的 Response,會被 HAProxy 偷偷加上 SERVERID 這個 Cookie,如下:
此外上述的「listen stats :8080」Section,我們還啟用監控工具(要關閉也可以),可以即時看到 HAPRoxy 的狀態,進入時需要輸入我們指定的帳號密碼,畫面如下:
啟用 SSL 加密+自動轉換 HTTPS 連線
除了分流之外,我們也常用 SSL 進行 HTTPS 連線,通常都會配合 HTTP Redirect,讓使用者輸入 HTTP 網址也能自動轉換,這些都可以直接透過 HAProxy 做掉,相當方便。開始之前我們先看一下要實作的架構,如下圖:
上圖中,使用者可以連進 HTTP 80 Port 與 HTTPS 443 Port,當沒有使用 SSL 連進 80 Port 時,HAProxy 會發出 HTTP 301 Redirect 將使用者導向HTTPS 服務。然而 HAProxy 會將 SSL 解開的封包再往後頭的 HTTP Cluster Web Server 傳送,好處是集中 SSL 加解密的動作在 HAProxy 上,後端的 Web Server 就容易管理。相關 haproxy.cfg 設定如下:
#自動將HTTP轉到HTTPS
frontend http_redirect
bind *:80
redirect scheme https code 301 if !{ ssl_fc }
frontend https_switch
bind *:443 ssl crt /etc/pki/CA/server.pem
mode http
option httpclose
option forwardfor
reqadd X-Forwarded-Proto:\ https
default_backend web_server_cluster
如果沒有 SSL 連線憑證,你也可以透過以下命令產生(當然這會被瀏覽器判斷為未認可):
sudo mkdir -p /etc/pki/CA/
sudo mkdir -p /etc/pki/CA/certs/
sudo mkdir -p /etc/pki/CA/private/
sudo openssl genrsa -out /etc/pki/CA/private/ca.key 2048
sudo openssl req -new -key /etc/pki/CA/private/ca.key -out /etc/pki/CA/certs/ssl.csr
sudo openssl x509 -req -days 3650 -in /etc/pki/CA/certs/ssl.csr -signkey /etc/pki/CA/private/ca.key -out /etc/pki/CA/certs/ssl.crt
還有一個重要的概念,由於 HAProxy 是採用 HTTP Proxy 機制,因此後端收到的連線都是由 HAProxy 這部電腦發出,如果想要抓到原始發送端的IP Address 必須透過「X-Forwarded-Proto」這個 HTTP Header 來取得,不要忘記。
HAProxy 除了 HTTP 分流,也可以做到最基本的 TCP/IP 分流,大致上常用到的功能都有,未來有機會再來介紹更複雜的設定與應用,今天先到這裡。