使用 HAProxy 完成 網站分流, 平衡負載

一台 Server 能夠承受的連線數量是有一定限制的, 特別是在同一時間的存取, 如果一台 Server 撐不住時, 該如何讓其它機器來分擔?

網站分流、平衡負載解法

Poor / Rich 版 優缺點

  • 窮人版解法 有些小問題: 機器掛掉時, 沒辦法 立刻(by TTL 的時間) 自動切換.
  • Rich 版 就蠻好搞定的, 只是這一版目前不適用在我身上. XD

HAProxy

由上述原因, 取中間值的話, 可以考慮用 HAProxy 來達成, 詳可見: HAProxy 官網 (註: 此份文件使用的 HAProxy 是 1.3.15 版)

HAProxy 可以設定後端有幾台機器, 多久要去 check 機器死活, 若死掉時就可以馬上將此機器從服務中抽離, 只要機器活起來, 將會自動回復服務, 基本架構可見: HAProxy - Description

HAProxy 架設

以下是於 Debian Linux 環境 步驟

  1. apt-get install haproxy
  2. vim /etc/default/haproxy # 將 ENABLED=0 改為 1

    #ENABLED=0
    ENABLED=1

  3. /etc/init.d/haproxy start # 啟動

HAProxy 錯誤排除

在上述啟動時, 若有出現下述錯誤:

Starting haproxy: [ALERT] 015/191034 (15631) : Starting proxy webfarm: cannot bind socket...on both load balancers

[ALERT] 056/103843 (1358) : Starting proxy www-balancer: cannot bind socket

解法

  • 暫時解法, 直接先修改設定, 讓它先跑起來:

    sysctl -e net.ipv4.ip_nonlocal_bind=1

  • 永久解法, 讓開機時自動設此參數.
    1. sysctl -a | grep nonlocal # 看是否已經有設定此參數
    2. vim /etc/sysctl.conf # 最下面加入
      net.ipv4.ip_nonlocal_bind=1

不過, 就直接啟動, 沒有做什麼任何的事情, 再來就來看看設定檔, 來把想做的事情設一設~ 🙂

HAProxy 設定檔 Debug 模式

HAProxy 的設定檔預設是放在 /etc/haproxy/haproxy.cfg (Debian), 要看是否設定正確, 來源資料是否走對路等等, 要先知道如何 Debug.

  • Debug mode 啟動: /usr/sbin/haproxy -d -f /etc/haproxy/haproxy.cfg

HAProxy 設定檔(haproxy.cfg)

HAProxy 設定檔, 詳細文件可見: HAProxy Documentation

想要直接取用設定(下述是我的設定), 可以直接修改取用(haproxy.cfg 下載), haproxy.cfg 內容如下:


global
    maxconn 32768
    #chroot /usr/share/haproxy
    user haproxy
    group haproxy
    daemon
    nbproc 8
    #debug
    #quiet

defaults
    log    global
    mode    http
    option    httplog
    option    dontlognull
    retries    3
    option redispatch
    option httpclose
    maxconn    32768
    contimeout    5000
    clitimeout    50000
    srvtimeout    50000

#listen    www-balancer 0.0.0.0:80
listen    www-balancer
        bind 0.0.0.0:80
        balance         roundrobin
        server          w1 11.11.11.11:80 weight 3 check
        server          w2 22.22.22.22:80 weight 3 check
        option          httpchk GET /robots.txt
        option          forwardfor

HAProxy 常用參數說明

HAProxy 上述 cfg 檔內容, 詳細可見: HAProxy Reference Manual (簡體版: HAProxy 配置手冊)

下述內容主要來自上述文件:

haproxy.cfg 三大項目

haproxy.cfg 有分下列三種: (haproxy.cfg 的三個主項目)

  • global
  • listen
  • defaults

註:

  • 下述所有 <name> 都必須由 大/小 寫字母, 數字, -, . : 組成. (大小寫會視為不同名稱)
  • defaults <name>: 下面所有參數的預設設定值, 下面的設定值會蓋掉上面的.
  • listen   <name>: 完整的 Proxy 代理, frontend / backend 都在這個設定裡 (用於 TCP)
global 分類

global 部分有下述幾類:

  • 行程管理和安全
    1. chroot <jail dir>
    2. daemon: 執行 -D 也是同樣
    3. gid
    4. group
    5. log
    6. nbproc: deamon 才能使用, 也是最推薦的模式, 如果小檔案很多, 建議要多開幾個, 但是 debug 時不建議開此參數. (arg: nbproc <number>)
    7. pidfile
    8. uid
    9. ulimit-n: 設定每個行程最大文件數, 此值會自動計算, 不建議設定此參數 (arg: ulimit-n <number>)
    10. user
    11. stats
  • 性能調校
    1. maxconn: 最大連接數, 同 -n (arg: maxconn <number>)
    2. noepoll: 在 Linux 系統不使用 epoll, 等同 -de
    3. nokqueue: 在 BSD 不使用 kqueue polling, 同 -dk
    4. nopoll: 此 poll 在任何機器都可以跑, 不建議關閉, 同 -dp
    5. nosepoll: 在 Linux 系統不使用 speculative epoll, 等同 -ds
    6. spread-checks: 多久去 check 一次, 預設值 0 (arg: spread-checks <0..50, in percent>)
    7. tune.maxaccept
    8. tune.maxpollevents
  • 測試
    1. debug: 將所有訊息都顯示到畫面上, 同 -d
    2. quiet: 不顯示任何訊息, 同 -v
listen 分類
  • listen <instance_name> [ <IP_address>:<port_range>[,...] ]

listen 部分有下述幾類:

  • bind
  • mode: TCP / HTTP / health
  • balance: roundrobin / source / url / url_param
  • server
  • option
  • # defaults 的參數都可於此寫入, 於此 listen 的設定中, 會以此寫入的為主.
defaults 參數

defaults 的參數說明: (註: 下述非完整參數, 只把可能會用到的簡單做個筆記.)

  • acl <aclname> <criterion> [flags] [operator] <value> ...
  • balance <algorithm> [ <arguments> ] (設定 load balancing algorithm, ex: balance roundrobin)
  • balance url_param <param> [check_post [<max_wait>]] (ex: balance url_param userid 或 balance url_param session_id check_post 64)
  • bind [<address>]:<port> [, ...] (ex: bind :80,:443 或 bind 10.0.0.1:10080,10.0.0.1:10443)
  • contimeout <timeout>: 設定連結到 server 的最大等待時間. 
  • clitimeout <timeout>: 設定 Client 最大等待時間
  • errorfile <code> <file> (ex: errorfile 400 /etc/haproxy/errors/400.http, <code> 支援的 HTTP status code 有:  400, 403, 408, 500, 502, 503, and 504.)
  • log global
  • log <address> <facility> [<level>] (ex: log 127.0.0.1:514 local0 notice)
  • maxconn <conns>: 同時最大連線數量
  • mode { tcp|http|health } (defaults 為 http)
  • monitor fail [if | unless] <condition>: 如果發現掛掉時, 要做什麼事.
  • monitor-net <source> (ex: monitor-net 192.168.0.252/31 # addresses .252 and .253 are just probing us.)
  • monitor-uri <uri> (ex: monitor-uri /haproxy_test # Use /haproxy_test to report haproxy's status)
  • option dontlognull: Enable or disable logging of null connections.
  • option forwardfor [ except <network> ]: 如果有 X-Forwarded-For header 都送到 server 去.
  • option httpchk: 於下面範例解釋
  • option httpclose: Enable or disable passive HTTP connection closing
  • option httplog: Enable logging of HTTP request, session state and timers
  • option logasap: Enable or disable early logging of HTTP requests
  • option persist: 當 client 連到死的機器時, 持續繼續連線, 搭配 redispatch 會再幫他導到其它機器.
  • option redispatch: 當 client 連到死的機器時, 重新再分配.
  • option smtpchk
  • option smtpchk <hello> <domain> (ex: option smtpchk HELO mydomain.org)
  • option srvtcpka: Enable or disable the sending of TCP keepalive packets on the server side
  • option ssl-hello-chk: Use SSLv3 client hello health checks for server testing
  • option tcpka: Enable or disable the sending of TCP keepalive packets on both sides
  • option tcplog: Enable advanced logging of TCP connections with session state and timers
  • option transparent: Enable client-side transparent proxying
  • reqadd <string>: Add a header at the end of the HTTP request
  • reqallow  <search> (ex: reqiallow ^Host:\ www\.)
  • reqiallow <search>  (ignore case) (ex: reqiallow ^Host:\ www\.)
  • reqdel  <search> (ex: reqdel ^X-Forwarded-For:.*)
  • reqidel <search>  (ignore case) (ex: reqidel ^Cookie:.*SERVER=)
  • reqdeny  <search>
  • reqideny <search>  (ignore case) (ex: reqideny  ^Host:\ .*\.local)
  • reqpass  <search>
  • reqipass <search>  (ignore case) (ex: reqipass  ^Host:\ www.private\.local)
  • reqrep  <search> <string> (ex: reqrep ^([^\ ]*)\ /static/(.*)  \1\ /\2)
  • reqirep <search> <string>   (ignore case) (ex: reqirep ^Host:\ www.mydomain.com   Host:\ www)
  • rspadd <string>: Add a header at the end of the HTTP response
  • rspdel  <search>
  • rspidel <search>  (ignore case)
  • server <name> <address>[:port] [param*]: Declare a server in a backend (ex: server first  10.1.1.1:1080 cookie first  check inter 1000 或 server second 10.1.1.2:1080 cookie second check inter 1000)
  • stats auth <user>:<passwd> (ex: stats auth admin1:AdMiN123)
  • srvtimeout <timeout>: 設定在 server side 的 最大等待時間
  • retries <number>: 重試次數
httpchk 範例

httpchk (啟用 HTTP 的 server health check.) 特別重要, 範例多記錄一點.


option httpchk
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
ex:
    # Relay HTTPS traffic to Apache instance and check service availability
    # using HTTP request "OPTIONS * HTTP/1.1" on port 80.
    backend https_relay
        mode tcp
        option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
        server apache1 192.168.1.1:443 check port 80
   
    option  httpchk GET /robots.txt
    option  httpchk GET /index.html
    option  httpchk *

option  httpchk GET /robots.txt # 指的是 GET /robots.txt HTTP/1.0
option  httpchk # 指的是 OPTIONS / HTTP/1.0
option  httpchk * # 指的是 OPTIONS * HTTP/1.0

相關網頁

作者: Tsung

對新奇的事物都很有興趣, 喜歡簡單的東西, 過簡單的生活.

在〈使用 HAProxy 完成 網站分流, 平衡負載〉中有 16 則留言

  1. stats enable
    stats hide-version
    stats scope .
    stats uri /admin?stats
    stats realm Haproxy\ Statistics
    stats auth admin:admin
    monitor-uri /haproxy_test
    我的還有加了這個
    看一下連線數的
    我在他的檔案中有看到一個haproxy.pl
    似乎是可以拿來和cacti 做結合....
    不過我弄了一天沒成功~~~就沒繼續用了....

  2. 大哥好
    小弟今天拿公司大流量的下載型網站做測試
    在無分流的狀況下
    執行 netstat -an |grep "80" |wc -l 連接數大約是25xx多
    但當我多準備兩台機器 一台haproxy 兩台web w1 和 w2
    設定完成功work之後
    再下指令 netstat -an |grep "80" |wc -l
    發現 ha 那台 居然25xxx w1 和 w2 各占一半約12xxx多
    請問這是什麼原因?(這個連接數的值也太高了吧.........)
    留下我的信箱 希望大哥指點 或討論一下!
    懇請賜教謝謝!!

  3. 不曉得是不是多一個 x? 多一位數? 是打錯還是?
    不然 25xx, w1 / w2 各一半 12xx, 這是正確的, haproxy 就是要幫你握 load balance 用, 各一半狀況很好~ 🙂

  4. 大哥好 我確定我沒打錯 ha 和 w1 w2 都破萬 但w1 w2 的連接數 確實是 ha那台的各占一半
    連接數破萬不知道是什麼原因?
    忘了解釋一下架構 sql一台 ha一台 w1 一台 w2 一台(共四台)
    ha 那台我還有做 nfs 方便改網頁資料不用w1 跟 w2 都改(是否跟這原因有關????)
    google搜尋了好久 似乎沒有人和我有相同問題
    admin管理查看介面也因為 流量太大有error 如果可以我是否能把圖截下來
    寄給您 幫我看一下呢?

  5. 嗯, 可以抓一下 error 我看看, 不過, 我不確定有沒有辦法解決.
    這個問題, 我也沒遇過... Orz.
    NFS 應該不是原因, 因為你看的是 80 port, 除非是 NFS 太慢, 把前端都卡住了.
    你可以先試試把檔案都擺到 w1, w2 上, 然後先不用 NFS 看看, 排除這個原因?

  6. 恩大哥 我排除是nfs的原因
    就如你所說的 也測了一下
    至於連接數 初步以為是被攻擊 可是弄了一下感覺又不像
    ha 本身 maxconn 32768 我能否讓他無限制 因為我的連接數肯定會超過這個值的!

  7. 大哥你好,最近在找load balance的資料
    先感謝你分享很多這方面的文章
    想請教一下
    我想找的load balance的演算法是使用最短的Response time(客戶端到server端)
    我找網路很多資料都說HAProxy之後會支援這演算法~
    但我還是找不到HAProxy這方面的資料~
    請問大哥是否知道HAProxy這方面的資料?
    還是知道有哪個load balance軟體有支援這種演算法?
    謝謝~

  8. 自動引用通知: HAProxy – Thinking more…

Tsung 發表迴響取消回覆

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料