国产精品免费无遮挡无码永久视频-国产高潮视频在线观看-精品久久国产字幕高潮-国产精品99精品无码视亚

洞察基的個人空間 http://www.4huy16.com/space-uid-170118.html [收藏] [復制] [RSS]

博客

粘性會話負載均衡 - MQTT Broker 集群詳解(二)

已有 678 次閱讀2022-7-26 15:28

在上一篇文章《MQTT Broker 集群詳解(一):負載均衡》中,我們簡單介紹了 MQTT 負載均衡:負載均衡既可以應用于傳輸層,也可以用于應用層。在本文中,我們將詳細介紹應用層負載均衡,其中最有趣的部分:粘性會話(sticky-session)。

本文由兩部分組成,第一部分將介紹 MQTT 會話,以及在分布式 MQTT Broker 集群中處理會話面臨的挑戰;第二部分是通過在 EMQX 4.3 集群前面配置 HAProxy 2.4 負載均衡器,帶讀者親自體驗如何充分利用粘性會話實現負載均衡。

MQTT 會話

為了持續接收消息,MQTT 客戶端通常會連接至 MQTT Broker 進行訂閱并保持長期連接。由于網絡問題或客戶端軟件維護等原因,連接可能會中斷一段時間,這并不罕見,但客戶端通常希望在重新連接成功后仍然能接收到中斷期間漏收的消息。

因此,為客戶端提供服務的 MQTT Broker 應該為客戶端保持會話(根據客戶端的請求,將「Clean-Session」標志設置為 false)。此時,即使客戶端斷開連接,訂閱者當前訂閱的主題以及傳遞給這些主題的消息(QoS1 和 2)等也會由消息服務器(broker)保留。

當具有持久會話的客戶端重新連接時,它不需要重新訂閱主題,消息服務器應該將所有未發送的消息發送給該客戶端。

我們之前寫過一篇關于 MQTT 會話的文章,如果您對 MQTT 會話的技術細節感興趣,可以通過閱讀這篇文章做進一步了解。

會話接管

當 MQTT Brokers 形成集群時,事情會變得更加復雜。從客戶端的角度來看,要連接的服務器不止一個,很難知道哪個服務器最適合連接。我們需要網絡中的另一個關鍵組件:負載均衡器。負載均衡器成為整個集群的接入點,并將客戶端的連接路由到集群中的某一個服務器。

如果客戶端通過負載均衡器連接到服務器(例如,node1),然后斷開連接并稍后重新連接,則新連接可能會路由到集群中的不同服務器(例如,node3)。在這種情況下,node3 應該在客戶端斷開連接時開始向客戶端發送未發送的消息。

實現集群范圍的持久會話有很多不同的策略。例如,整個集群可以共享一個全局存儲來保存客戶端的會話。

然而,更具可擴展性的解決方案通常以分布式方式解決這個問題,即數據從一個節點遷移到另一個節點。這種遷移稱為會話接管。會話接管應該對客戶端完全透明,但它是有代價的,尤其是當有很多消息需要處理時。

會話接管

粘性會話解決方案

這里的「粘性」一詞指的是負載均衡器能夠在重新連接時將客戶端路由到之前服務器的能力,這可以避免會話接管。當有許多客戶端在同一時間重新連接時,或者在一個有問題的客戶端反復斷開連接并再次連接的情況下,這是一個特別有用的功能。

為了讓負載均衡器以「粘性」方式分派連接,服務器需要知道連接請求中的客戶端標識符(有時是用戶名)——這需要負載均衡器檢查 MQTT 數據包以查找此類信息。

一旦獲得客戶端標識符(或用戶名),對于靜態集群,服務器可以將客戶端標識符(或用戶名)散列到服務器 ID。或者為了更好的靈活性,負載均衡器可以選擇維護一個從客戶端標識符(或用戶名)到目標節點 ID 的映射表。

在下一節中,我們將演示 HAProxy 2.4 中的粘性表策略。

使用 HAProxy 2.4 實現粘性會話

為了盡量減少先決條件,在這個演示集群中,我們將在 docker 容器中啟動兩個 EMQX 節點和一個 HAProxy 2.4。

創建 docker 網絡

為了使容器彼此連接,我們為它們創建了一個 docker 網絡。

docker network create test.net
啟動兩個 EMQX 4.3 節點

為了使節點彼此連接,應該在網絡名稱空間(test.net)中分配容器名稱和 EMQX 節點名稱。

啟動 node1
docker run -d \ --name n1.test.net \ --net test.net \ -e EMQX_NODE_NAME=emqx@n1.test.net \ -e EMQX_LISTENER__TCP__EXTERNAL__PROXY_PROTOCOL=on \ emqx/emqx:4.3.7
啟動 node2
docker run -d \ --name n2.test.net \ --net test.net \ -e EMQX_NODE_NAME=emqx@n2.test.net \ -e EMQX_LISTENER__TCP__EXTERNAL__PROXY_PROTOCOL=on \ emqx/emqx:4.3.7

注意環境變量

EMQX_LISTENER__TCP__EXTERNAL__PROXY_PROTOCOL. 該變量是為TCP監聽器啟用二進制代理協議,以便服務器可以獲得客戶端的真實 IP 地址信息,而不是負載均衡器的 IP 地址。

使 EMQX 節點加入集群
docker exec -it n2.test.net emqx_ctl cluster join emqx@n1.test.net

如果一切按預期進行,應該打印輸出這樣的日志:

[EMQX] emqx shutdown for join Join the cluster successfully. Cluster status: #{running_nodes => ['emqx@n1.test.net','emqx@n2.test.net'], stopped_nodes => []} <div class="copy-btn" data-clipboard-text="[EMQX] emqx shutdown for join Join the cluster successfully. Cluster status: #{running_nodes => ['emqx@n1.test.net','emqx@n2.test.net'], stopped_nodes => []} " style="box-sizing: inherit; cursor: pointer; position: absolute; top: 20px; right: 0px; width: 60px; height: 20px; font-size: 14px; line-height: 20px; text-align: center; color: rgb(134, 109, 255); background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAclBMVEUAAAAjIyMfHx8gICAeHh4jIyMfHx8eHh4eHh4eHh4dHR0fHx8eHh4eHh4eHh4dHR0dHR0eHh4dHR0eHh4eHh4eHh4dHR0eHh4eHh4eHh4eHh4eHh4eHh4dHR0eHh4dHR0dHR0eHh4eHh4eHh4dHR0dHR1LlvbwAAAAJXRSTlMAFhkgIiQpKzs8PUJFXXd6e4eMkJmprrK9w8Td3+Hm6/X4+fr9WCdMmgAAAMZJREFUOMvt1MkOgzAMBNCwUyi0hLWsATL//4s9VSKOpXKsUOc4etjJIQhx1UT1CDNzmzAuW2FHPywXKEiPdG6+aWtmiYpZk6OlVY+YgS5mc2/Z75iGQ7rCEUIIARj3UMw9lrsFoxVV7If+MWmDxaGwhmSO16CgcITHwBQdheaBP/Ex/OHvQg/jOShRn4BTXGGNvsIQAFQmTkzc+zIwqhkuA2940apFzsAKJa0SveV0piehAuvjp2Ze4Zoxa5J2Jmyso8v+jd85fiT1dzutbAAAAABJRU5ErkJggg==") 50% center / 20px 20px no-repeat rgb(246, 248, 250);">
啟動 HAProxy 2.4

創建文件 /tmp/haproxy.config,內容如下:

global   log stdout format raw daemon debug   nbproc 1   nbthread 2   cpu-map auto:1/1-2 0-1   # Enable the HAProxy Runtime API   # e.g. echo "show table emqx_tcp_back" | sudo socat stdio tcp4-connect:172.100.239.4:9999   stats socket :9999 level admin expose-fd listeners defaults   log global   mode tcp   option tcplog   maxconn 1024000   timeout connect 30000   timeout client 600s   timeout server 600s frontend emqx_tcp   mode tcp   option tcplog   bind *:1883   default_backend emqx_tcp_back backend emqx_tcp_back   mode tcp   # Create a stick table for session persistence   stick-table type string len 32 size 100k expire 30m   # Use ClientID / client_identifier as persistence key   stick on req.payload(0,0),mqtt_field_value(connect,client_identifier)   # send proxy-protocol v2 headers   server emqx1 n1.test.net:1883 check-send-proxy send-proxy-v2   server emqx2 n2.test.net:1883 check-send-proxy send-proxy-v2

在測試 docker 網絡中啟動 haproxy:

docker run -d \   --net test.net \   --name proxy.test.net \   -p 9999:9999 \   -v /tmp/haproxy.cfg:/haproxy.cfg \   haproxy:2.4 haproxy -f /haproxy.cfg
測試

現在我們使用流行的 mosquitto MQTT 客戶端(也在 docker 中)對其進行測試。

我們啟動一個訂閱者(名為 subscriber1)訂閱 t/# 主題

docker run --rm -it --net test.net eclipse-mosquitto \ mosquitto_sub -h proxy.test.net -t 't/#' -I subscriber1

然后從另一個客戶端向 t/xyz 發布一條 hello 消息

docker run --rm -it --net test.net eclipse-mosquitto \ mosquitto_pub -h proxy.test.net -t 't/xyz' -m 'hello'

如果一切都按預期進行,訂閱者應該打印出 hello 消息。

檢查 HAProxy 中的粘性表

我們還可以使用如下命令檢查在 HAProxy 中創建的粘性表。這需要 socat 命令,所以我們從 docker 主機運行它。

show table emqx_tcp_back" | sudo socat stdio tcp4-connect:127.0.0.1:9999

該命令應該打印當前連接,如下所示:

# table: emqx_external_tcp_listners, type: string, size:102400, used:1 0x7f930c033d90: key=subscriber1 use=0 exp=1793903 server_id=2 server_key=emqx2

在這個例子中,客戶端 subscriber1 被固定連接到服務器 emqx2。

結語

至此,我們可以了解到從客戶端的角度看,EMQX 集群是如何通過負載均衡器對外部提供服務的。

在本系列文章的后續內容中,我們將跟蹤一個 MQTT 消息從發布者到訂閱者的全過程,以便大家了解 EMQX 如何將它在集群中復制和轉發。敬請期待。

本系列中的其它文章

路過

雞蛋

鮮花

握手

雷人

評論 (0 個評論)

facelist

您需要登錄后才可以評論 登錄 | 立即注冊

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
返回頂部