[英]AWS application load balancer and socket.io
我有一個socket.io聊天室運行,當我們在一台機器上運行時,它的流量越來越大。 我們使用ws庫為套接字運行基准測試,它們的性能要好得多,這樣可以更好地利用我們的硬件。 這需要重寫我們的應用程序。
我們的socket.io應用程序允許用戶創建使用命名空間實現的私人聊天室。 例如
localhost:8080/room/1
localhost:8080/room/2
localhost:8080/room/3
當一切都在一個實例中時很容易,但現在我們正在尋求將這個容量擴展到多個節點。
我們在亞馬遜的雲中運行這個實例。 以前看起來像縮放websockets是ELB的一個問題。 我們注意到Amazon現在支持和支持websockets的應用程序負載均衡器。 這聽起來不錯,但在閱讀完文檔之后我必須承認我並不知道這意味着什么。 如果我使用帶有數千個命名空間的socket.io,我只是將實例放在這個ALB后面,一切都會起作用嗎?我的主要問題是:
如果x個用戶加入命名空間,ALB會自動將我的消息重定向到適當的用戶嗎? 所以假設我在ALB后面運行了5個vanilla socket.io實例。 用戶1創建名稱空間。 幾個小時后通過,用戶99999來了,並希望加入這個命名空間,是否需要編寫任何其他代碼來執行此操作,或者alb會重定向所有應該去的地方嗎? 發送和接收消息也是如此?
雖然ALB將正確地對用戶進行負載平衡,但您需要稍微調整一下代碼,因為加入特定房間的用戶將分散在不同的服務器中。
在他們的文檔中, socket.io提供了一種方法:
現在你有多個Socket.IO節點接受連接,如果你想向每個人(甚至某個房間里的每個人)廣播事件,你需要一些在進程或計算機之間傳遞消息的方法。
負責路由消息的接口就是我們所說的適配器。 您可以在socket.io-adapter之上實現自己的(通過繼承它),或者您可以使用我們在Redis上提供的那個:socket.io-redis:
var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
ALB設置
我建議在ALB中啟用粘性會話 ,否則socket.io握手在使用非websocket傳輸時會失敗,例如長輪詢,因為使用此傳輸的握手任務需要多個請求,並且您需要所有這些請求要對同一台服務器執行。
如果我想避免使用redis數據庫。 例如,如果我的房間是由用戶創建的,如果userA在實例4上創建了一個房間,如果另一個用戶想要加入這個房間,他們將如何知道它所在的實例? 我也需要適配器嗎?
此替代方案的目標是將每個房間分配給特定的EC2實例。 我們將使用ALB路由實現此目的
N個房間> 1個實例。
您需要將房間網址更改為:
/i1/room/550
/i1/room/20
/i2/room/5
/i5/room/492
存在:
/{instance-number}/room/{room-id}
這是必需的,因此ALB可以將每個房間路由到特定實例。
創建N個目標組(N是您此刻擁有的實例數)
將每個實例注冊到每個目標組
目標組>實例X目標組>目標選項卡>編輯>選擇實例X>添加到已注冊
Target group X > EC2 Instance X
Target group Y > EC2 Instance Y
編輯ALB目標規則
負載均衡器>您的ALB>監聽器>查看/編輯規則
使用以下設置為每個目標組/實例創建一個規則:
/iX/room/*
instanceX
輸入后進行此設置后:
/i1/room/550
您將使用EC2 Instance 1。 /i2/room/200
將使用EC2實例2 等等。
現在,您必須制定自己的邏輯,以便在您的實例之間保持平衡。 您不希望有一個實例托管幾乎所有組。
我推薦第一種方法,因為它可以輕松自動調整。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.