使用 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

對新奇的事物都很有興趣, 喜歡簡單的東西, 過簡單的生活.
本篇發表於 My_Note-Unix。將永久鏈結加入書籤。

使用 HAProxy 完成 網站分流, 平衡負載 有 15 則回應

  1. johnpupu 說道:

    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. Tsung 說道:

    感恩, 我再試試看~ 😀

  3. 丫忠 說道:

    感謝您對部份參數的翻譯以及提供相關網頁的連結,目前正想把HAProxy的架網架設起來試看看效果,有機會再請教您了

  4. Tsung 說道:

    加油~ 😀
    若我這邊有任何錯誤, 還請隨時跟我說~ 謝謝~ 🙂

  5. tunkai 說道:

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

  6. Tsung 說道:

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

  7. tunkai 說道:

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

  8. Tsung 說道:

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

  9. tunkai 說道:

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

  10. Tsung 說道:

    32768 這個你就給他設一個非常大的值就好囉? 🙂

  11. tunkai 說道:

    大哥我寄了一封信到你gmail
    查收一下
    謝謝!

  12. dylan 說道:

    文章不错,您的验证码plugins 叫做什么 盼复

  13. Cloud 說道:

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

發表迴響

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