WebSocket連線的負載均衡

2016-04-25    分類:作業系統、程式設計開發、首頁精華0人評論發表於2016-04-25

本文由碼農網 – 郝林偉原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

當管理大系統時,負載均衡的問題一直是一個熱點話題。負載均衡的目的是最優化資源使用,最大化吞吐量,最小化響應時間,避免任何單一資源的過載,因而解決這個問題對效能表現是很關鍵的。在本文中我們將看一看針對這個問題的一些解決方法。

為了更好的理解WS負載均衡,讓我們深入瞭解一下TCP套接字的背景知識。預設地,一個單獨的伺服器可以處理65536個套接字連線,因為65536是可用的最大的TCP埠數。因此,既然WS連線擁有TCP的特性,每個WS客戶端佔用一個埠,我們可以肯定地說WebSocket的連線數目也是有限的。

事實上,這隻說對了一半。對每個單獨的IP地址,伺服器都可以處理65536個套接字。因而通過向伺服器上新增額外的網路介面,就很容易擴充套件那個數量。與此同時,去追蹤伺服器上現有多少連結是極其重要的。一旦超出了限制範圍,你會遇到很多關於TCP連線的問題(例如,此時不可能通過ssh去連線到一個伺服器)。因而,在你的應用程式程式碼中限制每個節點的WS連線數是很好的主意。當我們處理WebSockets問題時也會在我們的apps中使用一樣的思路。

一旦我們理解了主要的限制條件,以及解決方式之後,讓我們開始考慮負載均衡。下面我將描述在我們自己的專案中試過的三種方式。請注意所有的系統部分都是部署在AWS上的,其中的一些技巧和提示只適用於Amazon配置。

ELB方法

實現負載均衡最簡單的辦法是直接使用AWS提供的Elastic Load Balancer方法。從ELB切換到TCP模式是很容易的,這就使得任何型別的TCP連線的負載均衡成為可能, 包括WebSockets。這個方法有如下特性:

  • LB的自動故障恢復;
  • 負載均衡節點的自動伸縮;
  • 非常簡單的設定。

基本上,對大多數情況而言它是一個很好的解決方案,在你遇到負載飛濺的增長情況之前。在這種情況下,ELB執行的很慢以至於無法建立新的連線。可以去聯絡Amazon,告訴他們去“預熱(pre-warm)”ELB,但是它對我們不是一個好的選項,基於負載測試的目的,當我們需要快速建立成千上萬的WS連線時;對客戶也不是好選項,基於系統的可用性。

軟體負載均衡器

我們曾經試過使用HAProxy作為一個負載均衡器。但是為了使HAProxy正確工作我們需要考慮上文討論的埠限制問題。為了使HAProxy能夠處理超過65536個連結,我們需要執行下面步驟:

1.建立一堆私有的IP地址。為了實現這個目的,選擇Amazon Instance -> Actions -> Networking -> Manage Private IP Addresses,我們新增三個IP地址:192.168.1.1,192.168.1.2,192.168.1.3。切記,IP要處於與你的真實應用程式伺服器同樣的子網中;

2.使用SSH連線到你的HAProxy例項,執行下面的命令:

$> ifconfig eth0:1 192.168.1.1
$> ifconfig eth0:2 192.168.1.2
$> ifconfig eth0:3 192.168.1.3

這些命令會往例項中新增3個虛擬網路介面;

3.配置HAProxy。這裡是haproxy.cfg檔案中的一段,用於3個Erlang節點接收WS連線。

listen erlang_front :8888
    mode        http
    balance     roundrobin
    timeout connect 1s
    timeout queue 5s
    timeout server 3600s
    option httpclose
    option forwardfor
    server      erlang-1 192.168.0.1:8888  source 192.168.1.1
    server      erlang-2 192.168.0.2:8888  source 192.168.1.2
    server      erlang-3 192.168.0.3:8888  source 192.168.1.3

現在,HAProxy能夠處理超過65536個WebSockets連結,通過增加虛擬網路介面,連線限制可以簡單地增長。同時,它也能非常快地建立新連線。這個方法看上去可行,儘管它有如下缺點:

  • 故障恢復的HAProxy例項需要使用類似Keepalived工具去手動建立;
  • 每次你增加一個新的Erlang節點,都要做些操作去重新配置HAProxy;
  • 隨著連線數目增長,沒有能水平伸縮HAProxy的選項。我們只有一個垂直選項可用,因此當我們有了越來越多的線上使用者後,我們需要越來越多的昂貴的HAProxy例項(以及HAProxy映象節點)。

對這些缺點我們也還覺得滿意,但是一個更簡單的方案已經被實現了。那是可能的,因為我們已經有了一些實現好的程式碼,而我們的系統設計也允許我們使用一個定製方法。

定製方法

在繼續前進之前,我們先回顧一下下面的圖,它顯示了我們系統的架構。

我們擁有一個JavaScript客戶端應用程式,一個auth應用負責使用者授權,一個Erlang應用實現主要的功能。資料流如下:

1.客戶端生成一個含有憑證的HTTP請求,傳送給Auth Application;

2.Auth Application檢查憑證,生成一個令牌,以一種HTTP請求的形式將它傳送給Erlang Cluster;

3.Erlang應用確認,令牌已經收到,給Auth應用返回一個包含配置資訊的HTTP響應;

4.Auth App給客戶端應用程式傳送一個HTTP響應。響應中包含生成的令牌;

5.客戶端使用令牌通過我們的HAProxy負載均衡器建立與Erlang應用之間的WebSocket連線。

這是我們基本的資料流,它被稍微修改了一點。我們新增一個簡單的模組到Erlang應用程式中去追蹤每個Erlang節點上的WebSocket連線數。基於Erlang“分散式的”特性,每個節點可以知道其它節點的連線數。因而,我們可以選擇一個擁有更少連線的節點,我們使用這個節點的公共IP地址,把它傳送回那個auth應用程式。然後那個auth應用程式將這個IP地址隨令牌返回到客戶端。客戶端使用接收到的IP地址和令牌去建立連線。因而,最終的圖顯示如下:

現在我們能夠:

  • 去掉WS負載均衡器,這就使得我們的系統變得不是那麼複雜;
  • 新增Erlang節點,而不用對系統其它部分進行重新配置。

除此之外:

  • 現在WS連線是平均分佈於Erlang節點之間的;
  • 系統很容易水平伸縮;
  • 對Erlang節點我們不需要使用Elastic IPs。

譯文連結:http://www.codeceo.com/article/websocket-load-balanced.html
英文原文:Load Balancing of WebSocket Connections
翻譯作者:碼農網 – 郝林偉
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章