首頁

目前文章總數:157 篇

  

最後更新:2024年 12月 07日

0062. 解決負載平衡下 SignalR 無法連線問題 - 啟用 Nginx Session黏著

日期:2024年 01月 21日

標籤: C# Asp.net Core Web MVC Web CentOS Nginx SignalR

摘要:C# 學習筆記


應用所需:1. Visual Studio 2022 以上,支援.net Core 6 WebSite
解決問題:1. 當使用SignalR時,若經過負載平衡 (GCP、Nginx、Azure...等),如何解決無法連線的問題,解決方法是用 Session Sticky(黏著)
範例檔案:基本SignalR範例 (原理可參考此篇)
基本介紹:本篇分為四大部分。
第一部分:前言 & 問題描述
第二部分:設定 SLB Session 黏著
第三部分:驗證結果
第四部份:遺留問題






第一部分:前言 & 問題描述

Step 1:前言 - 環境架構

上篇的 Server 配置:0061. Windows 作業系統下的 Nginx 伺服器負載平衡架設方法(Server Load Balancer, SLB)
加上此篇,部署 SignalR Server 兩台,所用代碼:0048. .Net Core 實現SignalR架設服務端,推播訊息到客戶端(前端、Android)
有以下架構,用戶可能有多個

Step 2:部署2台機器

部署兩台機器,將 appsetting.json 打開,為了分辨出是哪個站台


Step 3:執行啟動網站

到 Web1 目錄下,輸入下面指令,並設定 port:6001 啟動

dotnet SingalRWebsiteUseScaleOutAndBackPlateDatabaseExample.dll --urls=http://localhost:6001


然後到 Web2 目錄下,輸入下面指令,並設定 port:6002 啟動

dotnet SingalRWebsiteUseScaleOutAndBackPlateDatabaseExample.dll --urls=http://localhost:6002



Step 4:啟動 Nginx

到 windows for nginx 的 nginx 目錄下,點擊兩下啟動

Step 5:打開瀏覽器連線

連到主頁面 -> 開啟 F12 -> 在發送框輸入訊息 -> 可以成功推送

Step 6:問題發生 - 問題資訊

多按幾次F5 ,就會出現下面錯誤內容:

錯誤訊息:Error: Unable to connect to the server with any of the available transports. Error: WebSockets failed: Error: WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled. Error: ServerSentEvents failed: Error: EventSource failed to connect. The connection could not be found on the server, either the connection ID is not present on the server, or a proxy is refusing/buffering the connection. If you have multiple servers check that sticky sessions are enabled. Error: LongPolling failed: Error: No Connection with that ID: Status code '404'


大意是說:目前的 Client 與 Server 的連線ID 不一致,請檢察是否為使用Session 黏著



Step 7:問題發生 - 點出問題

對於 Step 6. 用下圖就很好理解了

[藍色] 一開始連線的時候,負載平衡導向到 Port:6001 做註冊
[深紅] 後續交互資訊時,負載平衡導向到另一台機器 Port:6002 做即時通信


因此 Port:6002 又不認識這個發訊息來的是誰,所以就報錯



第二部分:設定SLB Session黏著

Step 1:打開設定檔案

到 nginx 的目錄下,開啟 nginx.conf 檔案。貼上以下代碼在 upstream

ip_hash;



Step 2:重新開啟nginx

工作管理員 -> 關閉 nginx.exe -> 到 nginx 的目錄下,執行 nginx (如下圖)



第三部分:驗證結果

Step 1:打開瀏覽器連線

連到主頁面 -> 開啟 F12 -> 在發送框輸入訊息 -> 可以成功推送
並且無論如何重新整理,都會可以連線,不會再發生錯誤了



第四部分:遺留問題

Step 1:遺留問題 - 同個Port下

在多開網頁後,如果聊天室的夥伴在同個 Port 會可以正常聊天

Step 2:遺留問題

但是 Port 號不同的機器,在 Session 黏著下,就無法相互即時通信

Step 3:遺留問題 - 參考文獻

具體解決方案是 SignalR 採用橫向擴展的 backplane 方案。下篇會詳細說明具體作法。
參考 Microsoft 解法文獻:MSDN