ASP.NET Core的實時庫: SignalR簡介及使用

来源:https://www.cnblogs.com/cgzl/archive/2018/08/23/9515516.html
-Advertisement-
Play Games

ASP.NET Core的實時庫: SignalR簡介及使用 ...


大綱

本系列會分為2-3篇文章.

本文的內容:

 

SignalR

SignalR是一個.NET Core/.NET Framework的開源實時框架. SignalR的可使用Web Socket, Server Sent Events 和 Long Polling作為底層傳輸方式.

SignalR基於這三種技術構建, 抽象於它們之上, 它讓你更好的關註業務問題而不是底層傳輸技術問題.

SignalR這個框架分伺服器端和客戶端, 伺服器端支持ASP.NET Core 和 ASP.NET; 而客戶端除了支持瀏覽器里的javascript以外, 也支持其它類型的客戶端, 例如桌面應用.

 

回落機制

SignalR使用的三種底層傳輸技術分別是Web Socket, Server Sent Events 和 Long Polling.

其中Web Socket僅支持比較現代的瀏覽器, Web伺服器也不能太老.

而Server Sent Events 情況可能好一點, 但是也存在同樣的問題.

 

所以SignalR採用了回落機制, SignalR有能力去協商支持的傳輸類型.

Web Socket是最好的最有效的傳輸方式, 如果瀏覽器或Web伺服器不支持它的話, 就會降級使用SSE, 實在不行就用Long Polling.

 

一旦建立連接, SignalR就會開始發送keep alive消息, 來檢查連接是否還正常. 如果有問題, 就會拋出異常.

因為SignalR是抽象於三種傳輸方式的上層, 所以無論底層採用的哪種方式, SignalR的用法都是一樣的.

 

SignalR預設採用這種回落機制來進行傳輸和連接.

但是也可以禁用回落機制, 只採用其中一種傳輸方式.

 

RPC

RPC (Remote Procedure Call). 它的優點就是可以像調用本地方法一樣調用遠程服務.

SignalR採用RPC範式來進行客戶端與伺服器端之間的通信.

SignalR利用底層傳輸來讓伺服器可以調用客戶端的方法, 反之亦然, 這些方法可以帶參數, 參數也可以是複雜對象, SignalR負責序列化和反序列化.

 

Hub

Hub是SignalR的一個組件, 它運行在ASP.NET Core應用里. 所以它是伺服器端的一個類.

Hub使用RPC接受從客戶端發來的消息, 也能把消息發送給客戶端. 所以它就是一個通信用的Hub.

 

在ASP.NET Core里, 自己創建的Hub類需要繼承於基類Hub.

在Hub類裡面, 我們就可以調用所有客戶端上的方法了. 同樣客戶端也可以調用Hub類里的方法.

這種Hub+RPC的方式還是非常適合實時場景的.

 

之前說過方法調用的時候可以傳遞複雜參數, SignalR可以將參數序列化和反序列化. 這些參數被序列化的格式叫做Hub 協議, 所以Hub協議就是一種用來序列化和反序列化的格式.

Hub協議的預設協議是JSON, 還支持另外一個協議是MessagePack. MessagePack是二進位格式的, 它比JSON更緊湊, 而且處理起來更簡單快速, 因為它是二進位的.

此外, SignalR也可以擴展使用其它協議..

 

橫向擴展

隨著系統的運行, 有時您可能需要進行橫向擴展. 就是應用運行在多個伺服器上.

這時負載均衡器會保證每個進來的請求按照一定的邏輯分配到可能是不同的伺服器上.

在使用Web Socket的時候, 沒什麼問題, 因為一旦Web Socket的連接建立, 就像在瀏覽器和那個伺服器之間打開了隧道一樣, 伺服器是不會切換的.

但是如果使用Long Polling, 就可能有問題了, 因為使用Long Polling的情況下, 每次發送消息都是不同的請求, 而每次請求可能會到達不同的伺服器. 不同的伺服器可能不知道前一個伺服器通信的內容, 這就會造成問題.

針對這個問題, 我們需要使用Sticky Sessions (粘性會話).

 

Sticky Sessions 貌似有很多中實現方式, 但是主要是下麵要介紹的這種方式.

作為第一次請求的響應的一部分, 負載均衡器會在瀏覽器裡面設置一個Cookie, 來表示使用過這個伺服器. 在後續的請求里, 負載均衡器讀取Cookie, 然後把請求分配給同一個伺服器. 

 

在ASP.NET Core 中使用SignalR

建立項目

使用空模板建立ASP.NET Core項目.

建立一個CountService:

建立一個CountHub, 繼承於Hub:

 

配置SignalR

在Startup里註冊SignalR:

如果需要的話可以在AddSignalR()這個方法里使用lambda表達式進行一些配置.

 

然後在管道里使用SignalR, 使用app.UseSignalR():

這裡我已經建立了一個Hub, 叫做CountHub.

該方法的參數類型是Action<HubRouteBuilder>, 然後在這裡配置hub的路由.

 

使用Hub

首先建立一個Controller, 並註入IHubContext<CountHub>:

接下來我們就可以使用IHubContext<CountHub>這個對象與客戶端進行實時通信了.

 

下麵建立一個POST Action, 客戶端點擊按鈕之後來到這個Action, 在這裡我們使用hub為所有的客戶端發送一個消息:

這裡, 我調用了所有客戶端上的someFunc這個方法, 參數是一個對象.

但是使用這種IHubContext<Hub>的註入方式, 我們無法在它那取得Caller(調用該方法的客戶端)這個屬性.

 

Context

從Hub的Context屬性, 我們可以獲得用戶的信息.

我們在CountHub里override父類的一個方法OnConnectedAsync():

如果有新的連接建立了, 這個方法就會被執行.

在Hub類里, 我們可以訪問到Context屬性. 從Context屬性那, 我們可以獲得一個常用的屬性叫做ConnectionId. 這個ConnectionId就是連接到Hub的這個客戶端的唯一標識.

使用ConnectionId, 我們就可以取得這個客戶端, 並調用其方法, 如圖中的Clients.Client(connectionId).xxx.

Hub的Clients屬性表示客戶端, 它有若幹個方法可以選擇客戶端, 剛纔的Client(connectionId)就是使用connectionId找到這一個客戶端. 而AllExcept(connectionId)就是除了這個connectionId的客戶端之外的所有客戶端. 更多方法請查看文檔.

SignalR還有Group分組的概念, 而且操作簡單, 這裡用到的是Hub的Groups屬性. 向一個Group名添加第一個connectionId的時候, 分組就被建立. 移除分組內最後一個客戶端的時候, 分組就被刪除了. 使用Clients.Group("組名")可以調用組內客戶端的方法.

 

授權和驗證

SignalR會採用ASP.NET Core配置好的授權和驗證體系.

用法和Controller差不多:

 

想要取得User對象, 需要使用Context.User, 它的類型是ClaimsPrinciple:

客戶端

客戶端需要安裝signalr這個庫. 可以使用npm安裝 @aspnet/signalr

但是實際上只需要signalr.js一個文件即可.

客戶端代碼如下:

 

點擊按鈕後先執行Controller的POST方法, POST返回的是Accepted(1), 所以id是1.

 

使用singalR對象的HubConnectionBuilder來構建connection. 使用返回的connection對象, 我們可以用它的on方法來處理伺服器端方法調用的響應. 響應方法的參數可以是簡單類型也可以是複雜的對象.

使用connection.start()來打開連接, 使用catch()來捕獲異常, 使用connection.stop() 關閉連接.

 

先運行一下看看效果:

可以看到使用Clients.All, 所有的客戶端的方法都會被調用.

 

剛打開頁面的時候, 我們就嘗試建立連接, 從F12可以看到一個叫做negotiate的請求被髮送了:

 

這個請求的body如下:

可以看到客戶端選擇了一個connectionId,  裡面還有瀏覽器支持的傳輸方式.

伺服器的響應:

響應也包含著connectionId, 以及伺服器支持的傳輸方式. 這裡三種都支持. 由於我沒有指定傳輸方式, 所以SignalR選擇了最好的方式: websocket.

 

而在我點擊按鈕後, Web Socket連接才被初始化:

 

如果需要手動指定傳輸方式, 請在withUrl()方法的第二個參數指定傳輸方式: 

 

其它類型的客戶端

.NET 客戶端可以安裝 Microsoft.AspNetCore.SignalR.Client 這個包來支持SignalR.

具體用法請查看官方文檔, 語法和js的差不多.

 

MessagePack協議

需要安裝 Microsoft.AspNetCore.SignalR.Protocols.MessagePack.

然後在Startup裡面使用AddMessagePackProtocol()這個方法即可:

這樣的話, 伺服器端既支持JSON, 也支持MessagePack了.

另外.NET客戶端也需要安裝這個MessagePack包.

而js客戶端需要安裝 @aspnet/signalr-protocol-msgpack.

 

橫向擴展 Scale-out

可以採用Redis, 需要安裝 Microsoft.AspNetCore.SignalR.Redis. 這個包.

然後在Startup裡面配置:

 

這個沒試過, 請看官方文檔.

 

 

SignalR就介紹這些....

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • AOT是預編譯成本地程式,避免JIT動態編譯存在的性能問題。netcore一個吸引人的項目,就是基於coreRt 運行時的本地編譯技術,下麵我來替大家嘗試一下它究竟表現如何。 https://dotnet.myget.org/F/dotnet-core/api/v3/index.json Exe n... ...
  • 這個操作符重載很有意思 class Program { static void Main(string[] args) { Person person1 = new Person() { Name = "LiLei", Age = 12 }; Person person2 = new Person( ...
  • dotnet core 有一個轉變,他用dll格式來代替exe作為通用執行格式,然後要命令行dotnet yourApp.dll 來運行程式。為了提高逼格,雙擊可以運行,可以採用以下方案:方案一 用bat文件可以編寫一個bat來執行,如mylib.bat文件內容:@dotnet mylib.dll@... ...
  • 1 namespace 操作符重載 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Person person1 = new Person() { Name = "LiLei", Age = 12 }; 8 ... ...
  • asp.net Core 自定義埠 官方文檔 aspnet內庫源碼: "https://github.com/aspnet" dotnet系統內庫源碼: "https://github.com/dotnet" "asp.net core 官方文檔" 自定義埠訪問 webHost增加UseUrls ...
  • 0、目錄 整體架構目錄:ASP.NET Core分散式項目實戰-目錄 k8s架構目錄:Kubernetes(k8s)集群部署(k8s企業級Docker容器集群管理)系列目錄 此文閱讀目錄: 1、閑聊 2、部署流程介紹 3、部署Harbor倉庫 4、jenkins-slave鏡像搭建 5、部署jenk ...
  • 日誌作為快速定位程式問題的主要手段,日誌幾乎是所有程式都必須擁有的一部分,下麵我們就看下怎麼使用log4net.dll文件: 1.下載log4net.dll文件 2.創建自己的項目 3.在自己項目下的引用log4net.dll文件 4.在app.config配置文件里添加配置信息,下麵貼出配置信息, ...
  • 是因為webApi Views文件夾下缺乏web.config文件,從mvc項目相同目錄拷貝一個web.Config文件放入 刪除多餘的namespaces 即可 web.config配置如下: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...