日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

NetCore + SignalR 实现日志消息推送

發(fā)布時間:2023/12/4 综合教程 56 生活家
生活随笔 收集整理的這篇文章主要介紹了 NetCore + SignalR 实现日志消息推送 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

哈嘍大家周一好呀,感覺好久沒有寫文章了,上周出差了一次,感覺還是比坐辦公室好的多,平時在讀一本書《時生》,感興趣的可以看看?......

這幾天翻看 NetCore 相關(guān)知識擴(kuò)展的時候,發(fā)現(xiàn)了久違的一個知識點 —— SignalR ,為啥說久違呢,因為去年的時候,我在公司的項目里就想用了,后來組員說他學(xué)學(xué)看,也沒有了下文,我也就耽擱了,昨天突然看到這個了,想著正好看看吧,盡量落地到 NetCore 項目上,當(dāng)時我很自信的以為這個技術(shù)很老了,應(yīng)該用的人很多,可是天不遂人愿,在.Net MVC中使用的很多有六成,在NetCore 的小demo有兩成,NetCore + Vue 一起使用的就是寥寥無幾了,而且更多的是仿照官網(wǎng)的,好吧,我就簡單寫一個吧,希望對大家有所幫助,盡量將這個技術(shù)落地。

你一定很好奇,為啥要學(xué) SignalR ,或者說它有啥作用,那我先說幾個場景,你就知道了:

1、用戶登錄處理相關(guān)場景;?//平時我們是ajax請求,等待后端處理,然后返回 true ,根據(jù)返回結(jié)果相應(yīng)處理;

2、后端(c#)強(qiáng)制用戶退出登錄(js);?//這個后端還真沒有做過,沒啥思路

3、用戶支付訂單,等待成功后跳轉(zhuǎn);?//我以前用的是 ajax 輪詢,額。。。

4、給用戶發(fā)消息,或網(wǎng)頁內(nèi)簡單的聊天;

5、秒殺用戶名單,在頁面實時進(jìn)行滑動展示;

大家從這幾個栗子中,可以看到一個共性:

就是想用后端來操作前端,也就是說可以通過 服務(wù)端代碼,來控制前端 js 事件,來實現(xiàn)響應(yīng)式的實時場景過程,用戶完全不用做任何操作,或者做少量的操作就能實現(xiàn)更多的效果。

大家可以先自己用自己平時的想法和經(jīng)驗來實現(xiàn)上邊的場景,當(dāng)然并不是一定使用 SignalR ,Scoket 現(xiàn)在也是很火,本文就是簡單說說 SignalR 的基礎(chǔ)用法,想了想,怎么才能讓這個技術(shù)落地,最后決定將全部的操作日志通過 SignalR 的形式在Admin后臺展示出來吧,以后也試試強(qiáng)制登錄的功能

1、基本概念

本文重點說如何使用,但是為了文章的完整性,還是粘貼了一些概念講解,參考《ASP.NET Core SignalR 簡介》,更多的知識點請自行研究吧,網(wǎng)上這種概念類文章很多:

ASP.NET Core SignalR 是一個開源代碼庫,它簡化了向應(yīng)用添加實時 Web 功能的過程。?實時 Web 功能使服務(wù)器端代碼能夠即時將內(nèi)容推送到客戶端。

SignalR的可使用Web Socket, Server Sent Events 和 Long Polling作為底層傳輸方式。

SignalR 的適用對象:

  • 需要來自服務(wù)器的高頻率更新的應(yīng)用。?例如:游戲、社交網(wǎng)絡(luò)、投票、拍賣、地圖和 GPS 應(yīng)用。

  • 儀表板和監(jiān)視應(yīng)用。?示例包括公司儀表板、銷售狀態(tài)即時更新或行程警示。

  • 協(xié)作應(yīng)用。?協(xié)作應(yīng)用的示例包括白板應(yīng)用和團(tuán)隊會議軟件。

  • 需要通知的應(yīng)用。?社交網(wǎng)絡(luò)、電子郵件、聊天、游戲、行程警示以及許多其他應(yīng)用都使用通知。

SignalR 提供了一個用于創(chuàng)建服務(wù)器到客戶端 《遠(yuǎn)程過程調(diào)用(RPC》的 API。?RPC 通過服務(wù)器端 .NET Core 代碼調(diào)用客戶端上的 JavaScript 函數(shù)。

以下是 ASP.NET Core SignalR 的一些功能:

  • 自動管理連接。

  • 同時向所有連接的客戶端發(fā)送消息。?例如,聊天室。

  • 將消息發(fā)送到特定的客戶端或客戶端組。

  • 擴(kuò)展以處理增加的流量。

為啥要使用它,因為它是微軟的。?

2、支持平臺

服務(wù)端:ASP.NET Core SignalR 適用于 ASP.NET Core 支持的任何服務(wù)器平臺。

JS 客戶端:需要支持NodeJS 8+、或者常見主流瀏覽器都支持。

Java 客戶端:支持Java 8或更高版本。

Net 客戶端:可以在 ASP.NET Core 支持的任何平臺上運(yùn)行。?例如,?Xamarin 開發(fā)人員可以使用 SignalR用于構(gòu)建 Android 應(yīng)用程序使用 Xamarin.Android 8.4.0.1 或更高版本和 iOS 應(yīng)用程序使用 Xamarin.iOS 11.14.0.4 或更高版本。如果服務(wù)器運(yùn)行 IIS,Websocket 傳輸要求安裝 IIS 8.0 或更高版本在 Windows Server 2012 或更高版本。?其他傳輸在所有平臺上都受支持。

3、回落機(jī)制

參考文章《SignalR簡介及使用》

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

其中Web Socket僅支持比較現(xiàn)代的瀏覽器,Web服務(wù)器也不能太老;

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

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

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

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

SignalR默認(rèn)采用這種回落機(jī)制來進(jìn)行傳輸和連接。但是也可以禁用回落機(jī)制, 只采用其中一種傳輸方式。

4、Hub組件

Hub是SignalR的一個組件, 它運(yùn)行在ASP.NET Core應(yīng)用里. 所以它是服務(wù)器端的一個類;

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

在ASP.NET Core里, 自己創(chuàng)建的Hub類需要繼承于基類Hub;

在Hub類里面, 我們就可以調(diào)用所有客戶端上的方法了, 同樣客戶端也可以調(diào)用Hub類里的方法;

之前說過方法調(diào)用的時候可以傳遞復(fù)雜參數(shù), SignalR可以將參數(shù)序列化和反序列化, 這些參數(shù)被序列化的格式叫做Hub 協(xié)議,所以Hub協(xié)議就是一種用來序列化和反序列化的格式;

Hub協(xié)議的默認(rèn)協(xié)議是JSON, 還支持另外一個協(xié)議是MessagePack, MessagePack是二進(jìn)制格式的, 它比JSON更緊湊, 而且處理起來更簡單快速, 因為它是二進(jìn)制的;

此外, SignalR也可以擴(kuò)展使用其它協(xié)議。

好啦,復(fù)雜而又枯燥的概念說完了,接下來咱們開始動手寫代碼了!(額概念還是要看的?)

既然要實現(xiàn)實時交互,肯定得有服務(wù)端,那我們就直接在 Blog.Core 項目上,進(jìn)行處理吧

1、引用 SignalR 包

為了以后好拓展,我就把 SignalR 中心,也可以是通訊管道定義到了 Common 層,當(dāng)然可以自定義任意層。

//請看清,還有一個 Net 版本的,但是也能用,還是用 core 版本的吧
Install-Package Microsoft.AspNetCore.SignalR

2、聲明 Hub 管道——集線器

在 Blog.Core.Common 層,新建一個 Hubs 文件夾,然后添加一個 ChatHub 類:

 public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}

//定于一個通訊管道,用來管理我們和客戶端的連接
//1、客戶端調(diào)用 GetLatestCount,就像訂閱
public async Task GetLatestCount(string random)
{
//2、服務(wù)端主動向客戶端發(fā)送數(shù)據(jù),名字千萬不能錯
await Clients.All.SendAsync("ReceiveUpdate", LogLock.GetLogData());

//3、客戶端再通過 ReceiveUpdate ,來接收

}
}

基本的概念已經(jīng)在上邊了,大家結(jié)合之前的概念,應(yīng)該能看懂,看不懂也沒事兒,等看了下邊的 Vue 代碼,就理解了。

旁白:

這里說一下,上文中的GetLogData,這個方法,是直接把我們之前的日志從log文件給提取出來了,包括AOP日志,異常日志,Sql日志,因為格式規(guī)則變了,如果你本地已經(jīng)存在之前的錯誤日志了,請刪了文件重新生成,否則格式不正確會報錯。

3、配置服務(wù) 與 中間件

還是老規(guī)則,在netcore 中,基本只要涉及到Http請求相關(guān)的,一定要配置中間件,任何需要在宿主中用的服務(wù),都需要注入:

//這個配置就太簡單了,不細(xì)說了,大家一看就知道往哪里放
services.AddSignalR();


app.UseMvc();

//我這個放到了 Mvc 管道下邊,注意順序
app.UseSignalR(routes =>
{
//這里要說下,為啥地址要寫 /api/xxx
//因為我前后端分離了,而且使用的是代理模式,所以如果你不用/api/xxx的這個規(guī)則的話,會出現(xiàn)跨域問題,畢竟這個不是我的controller的路由,而且自己定義的路由
routes.MapHub<ChatHub>("/api/chatHub");
});

4、跨域

這一塊大家肯定都已經(jīng)配置好了,要不然不會前后端分離的,至于用前端 proxy 代理,還是后端 CORS 配置,看自己喜好吧,我更喜歡前者。

這個時候,我們的后端通道就打通了,如何驗證呢,我們在路由器直接輸入上邊的自定義路由地址即可:

?因為每次請求需要一個 ID 號的,直接訪問肯定不行,那這個 ID 我們怎么來拿呢,別著急,下文會說到,重點來了。

?服務(wù)端可以了,那就改配置客戶端了,其實客戶端特別簡單,就好像我們使用一個js庫插件一樣,比如大家一定用過地圖api庫 ,直接引用js,然后new map對象即可使用了,沒錯,SignalR和它一毛一樣。

1、安裝庫依賴包

?現(xiàn)在 vue 也和 core 很像了,用一個東西,都需要安裝包,配置服務(wù),再調(diào)用這三部曲了。

//直接在項目中執(zhí)行
npm install @aspnet/signalr

我為了更好的讓大家理解這個通訊的過程,每個標(biāo)題后邊,都破折號了我對這個過程的理解,大家一看就懂了。

2、添加引用——買個手機(jī)

在Admin 項目里,我增加了一個展示日志的頁面,大家自己看看就都懂了,然后之前是需要每次刷新的,但是這次改造成可以自推送的。

上邊也說到了,這個 SignalR 我們只需要像 map 地圖那樣,引用就行了,很簡單:

網(wǎng)上很坑的是,很多教程里竟然要在 main.js 中引用,最后導(dǎo)致還出現(xiàn)了依賴 Jquery 的各種bug,大家如果無聊可以試試。

3、開始連接到中心——連上網(wǎng)絡(luò)

?直接上代碼:

 created: function () {
//1、首先我們實例化一個連接器
this.connection = new signalR.HubConnectionBuilder()
//然后配置通道路由
.withUrl('/api/chatHub')
//日志信息
.configureLogging(signalR.LogLevel.Information)
//創(chuàng)建
.build();

var thisVue = this;
//開始連接
thisVue.connection.start();
},

?是不是很簡單,只需要我們在頁面初始化的時候,創(chuàng)建連接即可,只不過這里有一些小問題,

?咱們的項目中,已經(jīng)配置好了跨域,并且所有接口也已經(jīng)成功調(diào)用了,但是唯獨 Hub 卻不行,情況如下:

還記得上邊咱們在 startup.cs 中配置的 hub 路由么,如果我們不使用 /api/chatHub 會是怎么樣呢?這里我也簡單把錯誤的給寫出來,留作參考:

1、相對路徑,沒用代理規(guī)則:

withUrl('/axxxxx/chatHub')

是因為我們用的相對路徑,而且也沒與代理,系統(tǒng)會認(rèn)為我們訪問的是一個頁面路由,所以 404;

2、絕對路徑,沒用代理規(guī)則

withUrl('http://localhost:8081/axxxxx/chatHub')

?

這樣就會出現(xiàn)代理的問題。

當(dāng)然!如果你使用的是后端 CORS 機(jī)制跨域,不會這個問題的,其他的各種情況自己把握就好。

是不是我們這么配置好了就沒事了呢,別著急,還有要給bug,

3、服務(wù)器Nginx代理

如果你在服務(wù)器里用的是 Nginx 做代理的話,可能會遇到這個問題:

大家可以看看,這個錯誤,和上邊兩個都不一樣,是已經(jīng)連上了,但是去不能開啟數(shù)據(jù) 的交互 transport !神奇,簡單的看了看開源的 websockets 上提的 issues,是這么解決的《wss: Error during WebSocket handshake: Unexpected response code: 200?》

?

好啦!這次應(yīng)該沒啥問題了,繼續(xù)往下走。

4、客戶端調(diào)用集線器——呼叫對方

那我們現(xiàn)在已經(jīng)連接成功了,剩下的就是調(diào)用集線器了,也就是上邊我們定義的 Hub 通道,用來接收日志:

mounted() {

thisVue.connection.on('ReceiveUpdate', function (update) {
console.info('update success!')
thisVue.tableData = update;
window.clearInterval(this.t)
})

},

5、從集線器調(diào)用客戶端方法——接收回應(yīng)

?上邊我們是從客戶端去訂閱了一個 通道 連接,也就是說,我需要這個約定,那約定成功后,就需要接收來自服務(wù)器的通訊返回結(jié)果了,

thisVue.connection.on('ReceiveUpdate', function (update) {
console.info('update success!')
thisVue.tableData = update;//將返回的數(shù)據(jù),賦值給當(dāng)前頁面data
})

這個時候我們刷新頁面,已經(jīng)能看到消息了,然后我們在看看接口請求:

是不是很熟悉!沒錯,這個就是我們上邊說到的那個 ID ,不記得的往上看,這個是自動生成的,而且不隨著消息推送而變化,只有每次請求重新連接的時候,才會變化。?

好啦,這樣我們就成功了在頁面上展示出了我們的數(shù)據(jù),BUT!別慌,好像還沒有完成,因為我們現(xiàn)在僅僅是展示了出來,還沒有實現(xiàn)推送啊!別著急,既然一次能顯示,那多次也能顯示。

6、每次更新日志,推送到客戶端——實時短信

這個就很簡單了,我們只需要在每次日志產(chǎn)生的時候,來推送出來即可,舉個全局異常的栗子吧:

先注入我們的通道上下文:

 private readonly IHubContext<ChatHub> _hubContext;

public GlobalExceptionsFilter(IHostingEnvironment env, ILoggerHelper loggerHelper,
IHubContext<ChatHub> hubContext)
{
_env = env;
_loggerHelper = loggerHelper;
_hubContext = hubContext;
}

然后直接使用:

//采用log4net 進(jìn)行錯誤日志記錄

_loggerHelper.Error(json.Message,

WriteLog(json.Message, context.Exception));


_hubContext.Clients.All.SendAsync("ReceiveUpdate", LogLock.GetLogData()).Wait();

這樣,每次我們操作的時候,就會觸發(fā)生成日志的功能,同時再觸發(fā)推送功能,就這樣,我們把消息及時的推送了出去,達(dá)到了目的,實現(xiàn)了文章開頭的功能。

如果想中斷連接,只需要頁面關(guān)閉的時候,執(zhí)行 connection.stop() 即可。

?在文章開頭,我說了幾個場景,其他的不好實現(xiàn),先來個模擬登錄吧,就是把用戶名密碼傳到后臺,然后后臺將結(jié)果推送回來。

具體的流程就不說了,和上邊的是一樣的,只是很簡單的一個動作,接收下數(shù)據(jù)即可,

今天很簡單的實現(xiàn)了兩個小功能,一個是模擬登錄,一個是實時推送消息,大家學(xué)會了么,這里有幾個問題,大家可以思考思考:

1、SignalR到底能在平時開發(fā)中,使用哪些地方?

2、服務(wù)中心是如何將消息發(fā)出去的?

3、客戶端是如何來訂閱某一個通道集線器的?

4、SignalR的底層原理是什么?

5、如何關(guān)閉連接?

NetCore?https://github.com/anjoy8/Blog.Core

? ? ? ?Vue?https://github.com/anjoy8/Blog.Admin

原文地址:https://www.cnblogs.com/laozhang-is-phi/p/netcore-vue-signalr.html


.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?

總結(jié)

以上是生活随笔為你收集整理的NetCore + SignalR 实现日志消息推送的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。