關於負載平衡 (Load Balance)
現在很多網路服務都需要服務大量使用者,以前可以砸錢擴充機器硬體設施,但隨著網路服務的用量暴增,增加伺服器硬體設備已經無法解決問題。為了可以擴充服務,負載平衡成為主流的技術,這幾年雖然雲端與分散式儲存運算技術火紅,但是除非有特別的使用需求,不然在技術上 Load Balancing 算是比較容易達成與掌握的技術。負載平衡除了分流能力之外,有另一個很大的好處就是可以提供 High Availability,也就是傳說中的 HA 架構,好讓你一台機器掛了其他伺服器可以繼續服務,降低斷線率。
目前還使有很多大型網站都是使用典型的 Load Balance 架構,就像右圖由一台 Switch 或 Proxy 接收來自 Internet 的連線請求,然後分散給後端的 Cluster Server,藉此提高單個 IP 能夠服務與處理的連線量。除了上述的典型架構之外,也可透過 DNS 的搭配來分散流量,整提來說還算是好管理的架構。
這裡的典型架構最重要的就是 Load Balance 這台前端的 Gateway 了,如果購買 L4/L7 Switch 差不多要準備個 100W,設定也相當複雜。還好 Open Source 力量大,有 HAProxy 可以用,快來介紹如何使用吧!
Linux 安裝 HAProxy
套件安裝
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 皆適用)
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/
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 分流,大致上常用到的功能都有了,未來有機會我再來介紹更複雜的設定與應用,今天先到這裡,下台一鞠躬!