[開源軟件]負載均衡通信分發器(LB dispatch) - G5

負載均衡通信分發器(LB dispatch) - G5

1.開發背景
    今天和系統運維的老大聊天,談到一直在用的F5,行裏對其評價爲價格太高、功能複雜難懂,反正印象不是很好,使用前景不明。由於之前我曾經給行裏開發過一個通信中間件,附帶軟實現了負載均衡,幾年使用下來一直效果不錯,忽然想本身再軟實現一個純負載均衡通信分發器,並開源分享給你們。
    說幹就幹,回到家,搜了一下網上同類軟件,整理技術需求
    軟件定義以下:基於規則的通信分發器,匹配來源網絡地址,從哪一個端口進入,參照負載均衡算法轉發到目標網絡地址集合中的其中一個。
    實現目標以下:
    * 支持長/短TCP,後續還會支持UDP
    * 與應用層協議無關,即支持HTTP,FTP,TELNET,SSH等等全部應用層協議
    * 穩定高效,Linux下首選epoll(ET模式),全異步設計,也決定了目前僅支持Linux
    * 分發規則配置文件;也支持遠程在線管理規則,以及查詢狀態
    * 支持多種主流負載均衡算法
    * 源碼和可執行程序體型輕巧,概念簡單,使用快捷
    使用場景以下:
    * 通信轉發、分發
    * 與無負載均衡功能的通信軟件配合實現本地鏈接對端的負載均衡分發,避免改造通信軟件帶來的工做量和風險
    * 低成本的網站前端負載均衡通信網關
    
    研發以前,取個好聽的名字,相對於硬實現F5,就取名爲軟實現G5吧 ^_^
    通過5個晚上的奮筆疾書,搗鼓出v1.0.0,源代碼只有一個.c(2000行)和一個.h文件(200行),編譯連接出可執行程序約60KB大小。
    
2.安裝部署
    從http://git.oschina.net/calvinwilliams/G5下載源碼安裝包,在你的臨時目錄解開
    $ tar xvzf G5-x.x.x.tar.gz
    $ cd G5-x.x.x/src
    $ make -f makefile.Linux clean
    $ make -f makefile.Linux install
    由於只有一對源文件,因此編譯連接很快,也便於編譯器優化,更便於你本身手工編譯。
    若是不報錯的話,可執行程序G5就安裝到/usr/bin/下了。
    
3.基本使用
3.1.命令行參數
    不帶參數執行G5會顯示版本、命令行參數說明等信息
    $ G5
    G5 - tcp LB dispatch
    v1.0.0 build Apr  6 2014 15:00:31 WITH 100:1024:4096,10:3:100,64
    Copyright by calvin 2014
    Email : calvinwilliams.c @gmail.com
    
    USAGE : G5 -f config_pathfilename [ -r forward_rule_maxcount ] [ -s forward_session_maxcount ] [ -b transfer_bufsize ] [ -d ]
    
3.1.啓動
    由於是工具型軟件,因此用戶界面設計的比較簡單,自行編寫一個分發規則配置文件
    $ cat demo.conf
    admin      G        192.168.1.54:* - 192.168.1.54:8060 ;
    webdog     MS       192.168.1.54:* - 192.168.1.54:8070 > 192.168.1.79:8088 ;
    webdog2    RR       *.*.*.*:* - 192.168.1.54:8080 > 192.168.1.79:8089 192.168.1.79:8090 192.168.1.79:8091 ;
    做爲G5惟一一個必須的命令行參數-f啓動
    $ G5 -f demo.conf
    forward_rule_maxcount    [100]
    forward_session_maxcount [1024]
    transfer_bufsize         [4096]bytes
    epoll_create ok #3#
    admin G 192.168.1.54:* - 192.168.1.54:8060(LISTEN)#5# ;
    webdog MS 192.168.1.54:* - 192.168.1.54:8070(LISTEN)#7# > 192.168.1.79:8088 ;
    webdog2 RR *.*.*.*:* - 192.168.1.54:8080(LISTEN)#8# > 192.168.1.79:8089 192.168.1.79:8090 192.168.1.79:8091 ;
    ...
    以後產生的全部普通訊息、錯誤都輸出到標準輸出、錯誤輸出上,若是啓動參數加上-d,則還會輸出全部調試信息,如鏈接、斷開、數據分發
    
    我模擬發起一個HTTP請求
    $ lynx http://192.168.1.54:8080/index.php
    G5的標準輸出上產生以下信息
    forward2 [192.168.1.54:43477]#3# - [192.168.1.54:8080]#7# > [192.168.1.79:8089]#8#
    transfer #3# [324]bytes to #8#
    transfer #8# [257]bytes to #3#
    close #8# recv 0
    說明一下
    192.168.1.54:43477(lynx)鏈接192.168.1.54:8080(G5)被轉發到網站服務器192.168.1.79:8089(apache)
    lynx發送了HTTP請求324字節給網站服務器
    lynx從網站服務器接收了HTTP響應257字節
    服務端首先斷開鏈接
    
    通常都使用nohup使其變爲守護進程,輸出導向到文件
    $ nohup G5 demo.conf >demo.log 2>&1 &
    
3.2.中止
    別客氣,直接kill (pid)便可。
    
4.配置文件
    配置文件裏一行爲一條轉發規則,每條規則由三大段組成:規則名稱、規則類型和規則實體,之間用白字符(空格、TAB)隔開。
    規則名稱惟一標識該規則,便於新增、修改和刪除規則。
    規則類型說明該規則是在線管理(G),仍是以某種通信分發算法。目前實現的算法列表以下
    MS : 主備模式,即一直鏈接第一個目標地址,若是第一個目標地址故障了,切換到下一個目標地址
    RR : 輪詢模式,把全部目標地址按次序依次循環使用
    LC : 最少鏈接數模式,在目標地址集合中挑選當前最少鏈接的目標
    RT : 最小響應時間模式,在目標地址集合中挑選歷史數據交換最快的目標
    RD : 隨機模式,隨機選擇目標地址
    HS : HASH模式,根據來源地址計算HASH獲得一個惟一固定的目標地址
    規則實體格式爲"來源地址集合 - 本地轉發地址集合 > 目標地址集合 ;",其中三個地址集合內能夠包含一個地址或白字符隔開的地址列表。單個地址由"IP:PORT"組成。來源單個地址中的IP和PORT可使用'*'和'?'通配。當只有一個目標地址時,通信分發算法就沒有意義了。
    
    回來解釋一下前面展現的配置文件
    $ cat demo.conf
    # 只容許本機192.168.1.54鏈接到G5在線管理規則
    admin      G        192.168.1.54:* - 192.168.1.54:8060 ;
    # 本地全部TCP鏈接到本機8070端口時通通轉發到192.168.1.79:8088
    # 用於跨網段的通信轉發
    webdog     MS       192.168.1.54:* - 192.168.1.54:8070 > 192.168.1.79:8088 ;
    # 容許全部主機鏈接192.168.1.79:8089,並以輪詢算法分發給三個服務器192.168.1.79:8089 192.168.1.79:8090 192.168.1.79:8091
    # 用於網站前端負載均衡通信節點
    webdog2    RR       *.*.*.*:* - 192.168.1.54:8080 > 192.168.1.79:8089 192.168.1.79:8090 192.168.1.79:8091 ;
    還簡單吧
    
5.在線管理
    G5在啓動時必須指定一個配置文件裝載全部規則並以之工做,也支持遠程鏈接上管理端口在線管理規則,用telnet便可
    $ telnet 192.168.1.54 8060
    Trying 192.168.1.54...
    Connected to rhel54 (192.168.1.54).
    Escape character is '^]'.
    >
    '>'爲輸入提示符,後面能夠鍵入的命令有
    ver : 顯示G5版本及編譯日期時間
    quit : 斷開管理鏈接
    list rules : 顯示當前全部轉發規則
    add rule (...規則...) : 新增轉發規則
    modify rule (...規則...) : 修改轉發規則
    remove rule (規則名稱) : 刪除轉發規則
    dump rule : 保存全部轉發規則到啓動時指定的配置文件中
    list forwards : 顯示當前全部轉發鏈接信息
    
    使用示例
    $ telnet 192.168.1.54 8060
    Trying 192.168.1.54...
    Connected to rhel54 (192.168.1.54).
    Escape character is '^]'.
    > ver
    version v1.0.0 build Apr  3 2014 08:05:54
    > list rules
        1 : admin G 192.168.1.54:* - 192.168.1.54:8060 ;
        2 : webdog MS 192.168.1.54:* - 192.168.1.54:8070 > 192.168.1.79:8088 ;
        3 : webdog2 RR *.*.*.*:* - 192.168.1.54:8080 > 192.168.1.79:8089 192.168.1.79:8090 192.168.1.79:8091 ;
    > add rule webdog3 MS 192.168.1.54:* - 192.168.1.54:8070 > 192.168.1.79:8088 ;
    add forward rule ok
    > modify rule webdog3 HS 192.168.1.54:* - 192.168.1.54:8070 > 192.168.1.79:8088 ;
    modify forward rule ok
    > remove rule webdog3
    remove forward rule ok
    > dump rules
    dump all forward rules ok
    > list forwards
        1 : LISTEN [192.168.1.54:8060]#5#
        2 : LISTEN [192.168.1.54:8060]#6#
        3 : LISTEN [192.168.1.54:8070]#7#
        4 : LISTEN [192.168.1.54:8080]#8#
        5 : CLIENT [192.168.1.54:54162]#4# - MANAGE [192.168.1.54:8060]#5#
     2138 : CLIENT [192.168.1.54:39869]#11# < LISTEN [192.168.1.54:8080]#8# - SERVER [192.168.1.79:8090]#12# connected
     2139 : CLIENT [192.168.1.54:39869]#11# - LISTEN [192.168.1.54:8080]#8# > SERVER [192.168.1.79:8090]#12# connected
     2140 : CLIENT [192.168.1.54:39871]#27# < LISTEN [192.168.1.54:8080]#8# - SERVER [192.168.1.79:8091]#28# connected
     2141 : CLIENT [192.168.1.54:39871]#27# - LISTEN [192.168.1.54:8080]#8# > SERVER [192.168.1.79:8091]#28# connected
     2142 : CLIENT [192.168.1.54:39873]#17# < LISTEN [192.168.1.54:8080]#8# - SERVER [192.168.1.79:8089]#18# connected
     2143 : CLIENT [192.168.1.54:39875]#25# < LISTEN [192.168.1.54:8080]#8# - SERVER [192.168.1.79:8090]#26# connected
     2144 : CLIENT [192.168.1.54:39875]#25# - LISTEN [192.168.1.54:8080]#8# > SERVER [192.168.1.79:8090]#26# connected
     2145 : CLIENT [192.168.1.54:39873]#17# - LISTEN [192.168.1.54:8080]#8# > SERVER [192.168.1.79:8089]#18# connected
     2146 : CLIENT [192.168.1.54:39877]#21# < LISTEN [192.168.1.54:8080]#8# - SERVER [192.168.1.79:8091]#22# connected
     2147 : CLIENT [192.168.1.54:39877]#21# - LISTEN [192.168.1.54:8080]#8# > SERVER [192.168.1.79:8091]#22# connected
     2148 : CLIENT [192.168.1.54:39879]#9# < LISTEN [192.168.1.54:8080]#8# - SERVER [192.168.1.79:8089]#10# connected
     2149 : CLIENT [192.168.1.54:39879]#9# - LISTEN [192.168.1.54:8080]#8# > SERVER [192.168.1.79:8089]#10# connected
     2150 : CLIENT [192.168.1.54:39881]#15# < LISTEN [192.168.1.54:8080]#8# - SERVER [192.168.1.79:8090]#16# connected
     2151 : CLIENT [192.168.1.54:39881]#15# - LISTEN [192.168.1.54:8080]#8# > SERVER [192.168.1.79:8090]#16# connected
     2152 : CLIENT [192.168.1.54:39883]#19# < LISTEN [192.168.1.54:8080]#8# - SERVER [192.168.1.79:8091]#20# connected
     2153 : CLIENT [192.168.1.54:39884]#23# < LISTEN [192.168.1.54:8080]#8# - SERVER [192.168.1.79:8089]#24# connected
     2154 : CLIENT [192.168.1.54:39884]#23# - LISTEN [192.168.1.54:8080]#8# > SERVER [192.168.1.79:8089]#24# connected
     2155 : CLIENT [192.168.1.54:39883]#19# - LISTEN [192.168.1.54:8080]#8# > SERVER [192.168.1.79:8091]#20# connected
     2156 : CLIENT [192.168.1.54:39887]#13# < LISTEN [192.168.1.54:8080]#8# - SERVER [192.168.1.79:8090]#14# connected
     2157 : CLIENT [192.168.1.54:39887]#13# - LISTEN [192.168.1.54:8080]#8# > SERVER [192.168.1.79:8090]#14# connected
    > quit
    Connection closed by foreign host.
    $
    
6.性能測試
    由於是簡單的通信轉發、分發器,內部使用epoll(ET)+全異步實現,達到高併發和充分負載均衡,幾乎能夠榨乾單核硬件資源。
    因爲我沒有完整靠譜的壓測環境,只能在個人老爺機上作直連和經過G5轉連的性能比較差別。
    
    壓測硬件(2007年買的老爺機)
        CPU  : Intel Dual E2160 1.8GHz 1.81GHz
        內存 : 2GB
        硬盤 : 希捷 250GB 7200轉
    壓測軟件
        Windows XP SP3 ( VMware 6.0 ( RedHat Enterprise Linux 5.4 分了256MB內存 ) )
    壓測場景
        ab直連apache 和 ab經過G5轉發給apache
        併發數100,總請求數10000次
    
    首先是192.168.1.54:*(apache ab)直連192.168.1.79:8090(apache 2.2.13 for win32),

    Server Software:        Apache/2.2.13
    Server Hostname:        192.168.1.79
    Server Port:            8090
    
    Document Path:          /index.html
    Document Length:        44 bytes
    
    Concurrency Level:      100
    Time taken for tests:   12.503706 seconds
    Complete requests:      10000
    Failed requests:        0
    Write errors:           0
    Total transferred:      3160000 bytes
    HTML transferred:       440000 bytes
    Requests per second:    799.76 [#/sec] (mean)
    Time per request:       125.037 [ms] (mean)
    Time per request:       1.250 [ms] (mean, across all concurrent requests)
    Transfer rate:          246.73 [Kbytes/sec] received
    
    Connection Times (ms)
                 min  mean[+/-sd] median   max
    Connect:        0    0   4.4      0      86
    Processing:    11  123  31.7    113     283
    Waiting:        8  122  31.6    112     281
    Total:         28  123  31.9    113     284
    
    Percentage of the requests served within a certain time (ms)
     50%    113
     66%    115
     75%    117
     80%    120
     90%    163
     95%    187
     98%    249
     99%    256
    100%    284 (longest request)

    而後是192.168.1.54:*(apache ab)發往192.168.1.54:8080(G5)(主備模式MS)分發給192.168.1.79:8089,8090,8091(apache 2.2.13 for win32),

    Server Software:        Apache/2.2.13
    Server Hostname:        192.168.1.54
    Server Port:            8080
    
    Document Path:          /index.html
    Document Length:        44 bytes
    
    Concurrency Level:      100
    Time taken for tests:   14.235889 seconds
    Complete requests:      10000
    Failed requests:        0
    Write errors:           0
    Total transferred:      3160000 bytes
    HTML transferred:       440000 bytes
    Requests per second:    702.45 [#/sec] (mean)
    Time per request:       142.359 [ms] (mean)
    Time per request:       1.424 [ms] (mean, across all concurrent requests)
    Transfer rate:          216.71 [Kbytes/sec] received
    
    Connection Times (ms)
                 min  mean[+/-sd] median   max
    Connect:        0    0   8.3      0     154
    Processing:    25  140  31.3    132     335
    Waiting:       22  139  31.2    131     334
    Total:         70  140  32.3    132     338
    
    Percentage of the requests served within a certain time (ms)
     50%    132
     66%    134
     75%    137
     80%    140
     90%    175
     95%    190
     98%    275
     99%    295
    100%    338 (longest request)

    而後是192.168.1.54:*(apache ab)發往192.168.1.54:8080(G5)(輪詢模式RR)分發給192.168.1.79:8089,8090,8091(apache 2.2.13 for win32),

    Server Software:        Apache/2.2.13
    Server Hostname:        192.168.1.54
    Server Port:            8080
    
    Document Path:          /index.html
    Document Length:        44 bytes
    
    Concurrency Level:      100
    Time taken for tests:   14.15712 seconds
    Complete requests:      10000
    Failed requests:        0
    Write errors:           0
    Total transferred:      3160316 bytes
    HTML transferred:       440044 bytes
    Requests per second:    713.48 [#/sec] (mean)
    Time per request:       140.157 [ms] (mean)
    Time per request:       1.402 [ms] (mean, across all concurrent requests)
    Transfer rate:          220.18 [Kbytes/sec] received
    
    Connection Times (ms)
                 min  mean[+/-sd] median   max
    Connect:        0    0   7.5      0     140
    Processing:    26  137  67.8     91     342
    Waiting:       25  137  67.8     90     340
    Total:         49  138  68.1     91     347
    
    Percentage of the requests served within a certain time (ms)
     50%     91
     66%    178
     75%    219
     80%    222
     90%    229
     95%    259
     98%    273
     99%    279
    100%    347 (longest request)

    而後是192.168.1.54:*(apache ab)發往192.168.1.54:8080(G5)(最小響應時間模式RT)分發給192.168.1.79:8089,8090,8091(apache 2.2.13 for win32),

    Server Software:        Apache/2.2.13
    Server Hostname:        192.168.1.54
    Server Port:            8080
    
    Document Path:          /index.html
    Document Length:        44 bytes
    
    Concurrency Level:      100
    Time taken for tests:   14.260485 seconds
    Complete requests:      10000
    Failed requests:        0
    Write errors:           0
    Total transferred:      3160000 bytes
    HTML transferred:       440000 bytes
    Requests per second:    701.24 [#/sec] (mean)
    Time per request:       142.605 [ms] (mean)
    Time per request:       1.426 [ms] (mean, across all concurrent requests)
    Transfer rate:          216.33 [Kbytes/sec] received
    
    Connection Times (ms)
                 min  mean[+/-sd] median   max
    Connect:        0    0   7.7      0     148
    Processing:    29  140  27.3    133     346
    Waiting:       26  139  27.2    132     346
    Total:         65  141  28.4    133     346
    
    Percentage of the requests served within a certain time (ms)
     50%    133
     66%    136
     75%    138
     80%    140
     90%    181
     95%    190
     98%    241
     99%    287
    100%    346 (longest request)

    而後是192.168.1.54:*(apache ab)發往192.168.1.54:8080(G5)(隨機模式RD)分發給192.168.1.79:8089,8090,8091(apache 2.2.13 for win32),

    Server Software:        Apache/2.2.13
    Server Hostname:        192.168.1.54
    Server Port:            8080
    
    Document Path:          /index.html
    Document Length:        44 bytes
    
    Concurrency Level:      100
    Time taken for tests:   14.114779 seconds
    Complete requests:      10000
    Failed requests:        0
    Write errors:           0
    Total transferred:      3160632 bytes
    HTML transferred:       440088 bytes
    Requests per second:    708.48 [#/sec] (mean)
    Time per request:       141.148 [ms] (mean)
    Time per request:       1.411 [ms] (mean, across all concurrent requests)
    Transfer rate:          218.64 [Kbytes/sec] received
    
    Connection Times (ms)
                 min  mean[+/-sd] median   max
    Connect:        0    0   7.3      0     139
    Processing:    22  138  67.3     92     354
    Waiting:       21  138  67.3     92     353
    Total:         48  139  67.6     92     356
    
    Percentage of the requests served within a certain time (ms)
     50%     92
     66%    184
     75%    212
     80%    221
     90%    239
     95%    255
     98%    279
     99%    292
    100%    356 (longest request)
    
    能夠看出,轉發的總耗時比直連多了10%左右,大致仍是能夠接受的,若是G5和WebServer分開部署在不一樣機器裏,G5就能發揮出負載均衡的優點,性能也會大幅提高。
    之後如有更好的環境,我將會作更全面更深刻的壓測。

7.待開發內容
    * 轉發時,若是接收速度比發送快,暫禁接收sock的EPOLLIN,啓用發送sock的EPOLLOUT異步等待準備好再發送
    * 最大鏈接數控制
    * 鏈接超時控制

8.最後
    做爲一個通信分發(負載均衡)網絡工具,G5基本實現設計目標,併發布初版出來分享給開源世界,歡迎試用。
    G5源代碼做爲epoll(ET)+全異步綜合使用示例也供你們學習參考,歡迎批評指正。
    若有問題或建議請及時聯繫我,讓咱們共同把她搞大!
    開源項目首頁 : http://git.oschina.net/calvinwilliams/G5
    做者郵箱 : calvinwilliams.c @gmail.com
相關文章
相關標籤/搜索