NetCore + SignalR 实现日志消息推送

哈喽大家周一好呀,感觉好久没有写文章了,上周出差了一次,感觉还是比坐办公室好的多,平时在读一本书《时生》,感兴趣的可以看看?......

这几天翻看 NetCore 相关知识扩展的时候,发现了久违的一个知识点 —— SignalR ,为啥说久违呢,因为去年的时候,我在公司的项目里就想用了,后来组员说他学学看,也没有了下文,我也就耽搁了,昨天突然看到这个了,想着正好看看吧,尽量落地到 NetCore 项目上,当时我很自信的以为这个技术很老了,应该用的人很多,可是天不遂人愿,在.Net MVC中使用的很多有六成,在NetCore 的小demo有两成,NetCore + Vue 一起使用的就是寥寥无几了,而且更多的是仿照官网的,好吧,我就简单写一个吧,希望对大家有所帮助,尽量将这个技术落地。

你一定很好奇,为啥要学 SignalR ,或者说它有啥作用,那我先说几个场景,你就知道了:

1、用户登录处理相关场景; //平时我们是ajax请求,等待后端处理,然后返回 true ,根据返回结果相应处理;

2、后端(c#)强制用户退出登录(js); //这个后端还真没有做过,没啥思路

3、用户支付订单,等待成功后跳转; //我以前用的是 ajax 轮询,额。。。

4、给用户发消息,或网页内简单的聊天;

5、秒杀用户名单,在页面实时进行滑动展示;

大家从这几个栗子中,可以看到一个共性:

就是想用后端来操作前端,也就是说可以通过 服务端代码,来控制前端 js 事件,来实现响应式的实时场景过程,用户完全不用做任何操作,或者做少量的操作就能实现更多的效果。

大家可以先自己用自己平时的想法和经验来实现上边的场景,当然并不是一定使用 SignalR ,Scoket 现在也是很火,本文就是简单说说 SignalR 的基础用法,想了想,怎么才能让这个技术落地,最后决定将全部的操作日志通过 SignalR 的形式在Admin后台展示出来吧,以后也试试强制登录的功能

1、基本概念

本文重点说如何使用,但是为了文章的完整性,还是粘贴了一些概念讲解,参考《ASP.NET Core SignalR 简介》,更多的知识点请自行研究吧,网上这种概念类文章很多:

ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程。 实时 Web 功能使服务器端代码能够即时将内容推送到客户端。

SignalR的可使用Web Socket, Server Sent Events 和 Long Polling作为底层传输方式。

SignalR 的适用对象:

  • 需要来自服务器的高频率更新的应用。 例如:游戏、社交网络、投票、拍卖、地图和 GPS 应用。

  • 仪表板和监视应用。 示例包括公司仪表板、销售状态即时更新或行程警示。

  • 协作应用。 协作应用的示例包括白板应用和团队会议软件。

  • 需要通知的应用。 社交网络、电子邮件、聊天、游戏、行程警示以及许多其他应用都使用通知。

SignalR 提供了一个用于创建服务器到客户端 《远程过程调用(RPC》的 API。 RPC 通过服务器端 .NET Core 代码调用客户端上的 JavaScript 函数。

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

  • 自动管理连接。

  • 同时向所有连接的客户端发送消息。 例如,聊天室。

  • 将消息发送到特定的客户端或客户端组。

  • 扩展以处理增加的流量。

为啥要使用它,因为它是微软的。 

2、支持平台

服务端:ASP.NET Core SignalR 适用于 ASP.NET Core 支持的任何服务器平台。

JS 客户端:需要支持NodeJS 8+、或者常见主流浏览器都支持。

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

Net 客户端:可以在 ASP.NET Core 支持的任何平台上运行。 例如, Xamarin 开发人员可以使用 SignalR用于构建 Android 应用程序使用 Xamarin.Android 8.4.0.1 或更高版本和 iOS 应用程序使用 Xamarin.iOS 11.14.0.4 或更高版本。如果服务器运行 IIS,Websocket 传输要求安装 IIS 8.0 或更高版本在 Windows Server 2012 或更高版本。 其他传输在所有平台上都受支持。

3、回落机制

参考文章《SignalR简介及使用》

SignalR使用的三种底层传输技术分别是Web Socket, Server Sent Events 和 Long Polling;

其中Web Socket仅支持比较现代的浏览器,Web服务器也不能太老;

而Server Sent Events 情况可能好一点, 但是也存在同样的问题。

Web Socket是最好的最有效的传输方式, 如果浏览器或Web服务器不支持它的话, 就会降级使用SSE, 实在不行就用Long Polling;

一旦建立连接, SignalR就会开始发送keep alive消息, 来检查连接是否还正常, 如果有问题, 就会抛出异常;

因为SignalR是抽象于三种传输方式的上层, 所以无论底层采用的哪种方式, SignalR的用法都是一样的;

SignalR默认采用这种回落机制来进行传输和连接。但是也可以禁用回落机制, 只采用其中一种传输方式。

4、Hub组件

Hub是SignalR的一个组件, 它运行在ASP.NET Core应用里. 所以它是服务器端的一个类;

Hub使用RPC接受从客户端发来的消息, 也能把消息发送给客户端, 所以它就是一个通信用的Hub;

在ASP.NET Core里, 自己创建的Hub类需要继承于基类Hub;

在Hub类里面, 我们就可以调用所有客户端上的方法了, 同样客户端也可以调用Hub类里的方法;

之前说过方法调用的时候可以传递复杂参数, SignalR可以将参数序列化和反序列化, 这些参数被序列化的格式叫做Hub 协议,所以Hub协议就是一种用来序列化和反序列化的格式;

Hub协议的默认协议是JSON, 还支持另外一个协议是MessagePack, MessagePack是二进制格式的, 它比JSON更紧凑, 而且处理起来更简单快速, 因为它是二进制的;

此外, SignalR也可以扩展使用其它协议。

好啦,复杂而又枯燥的概念说完了,接下来咱们开始动手写代码了!(额概念还是要看的?)

既然要实现实时交互,肯定得有服务端,那我们就直接在 Blog.Core 项目上,进行处理吧

1、引用 SignalR 包

为了以后好拓展,我就把 SignalR 中心,也可以是通讯管道定义到了 Common 层,当然可以自定义任意层。

//请看清,还有一个 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、客户端调用 GetLatestCount,就像订阅
public async Task GetLatestCount(string random)
{
//2、服务端主动向客户端发送数据,名字千万不能错
await Clients.All.SendAsync("ReceiveUpdate", LogLock.GetLogData());

//3、客户端再通过 ReceiveUpdate ,来接收

}
}

基本的概念已经在上边了,大家结合之前的概念,应该能看懂,看不懂也没事儿,等看了下边的 Vue 代码,就理解了。

旁白:

这里说一下,上文中的GetLogData,这个方法,是直接把我们之前的日志从log文件给提取出来了,包括AOP日志,异常日志,Sql日志,因为格式规则变了,如果你本地已经存在之前的错误日志了,请删了文件重新生成,否则格式不正确会报错。

640?wx_fmt=png

3、配置服务 与 中间件

还是老规则,在netcore 中,基本只要涉及到Http请求相关的,一定要配置中间件,任何需要在宿主中用的服务,都需要注入:

//这个配置就太简单了,不细说了,大家一看就知道往哪里放
services.AddSignalR();


app.UseMvc();

//我这个放到了 Mvc 管道下边,注意顺序
app.UseSignalR(routes =>
{
//这里要说下,为啥地址要写 /api/xxx
//因为我前后端分离了,而且使用的是代理模式,所以如果你不用/api/xxx的这个规则的话,会出现跨域问题,毕竟这个不是我的controller的路由,而且自己定义的路由
routes.MapHub<ChatHub>("/api/chatHub");
});

4、跨域

这一块大家肯定都已经配置好了,要不然不会前后端分离的,至于用前端 proxy 代理,还是后端 CORS 配置,看自己喜好吧,我更喜欢前者。

这个时候,我们的后端通道就打通了,如何验证呢,我们在路由器直接输入上边的自定义路由地址即可:

640?wx_fmt=png

 因为每次请求需要一个 ID 号的,直接访问肯定不行,那这个 ID 我们怎么来拿呢,别着急,下文会说到,重点来了。

 服务端可以了,那就改配置客户端了,其实客户端特别简单,就好像我们使用一个js库插件一样,比如大家一定用过地图api库 ,直接引用js,然后new map对象即可使用了,没错,SignalR和它一毛一样。

1、安装库依赖包

 现在 vue 也和 core 很像了,用一个东西,都需要安装包,配置服务,再调用这三部曲了。

//直接在项目中执行
npm install @aspnet/signalr

我为了更好的让大家理解这个通讯的过程,每个标题后边,都破折号了我对这个过程的理解,大家一看就懂了。

2、添加引用——买个手机

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

上边也说到了,这个 SignalR 我们只需要像 map 地图那样,引用就行了,很简单:

640?wx_fmt=png

网上很坑的是,很多教程里竟然要在 main.js 中引用,最后导致还出现了依赖 Jquery 的各种bug,大家如果无聊可以试试。

3、开始连接到中心——连上网络

 直接上代码:

 created: function () {
//1、首先我们实例化一个连接器
this.connection = new signalR.HubConnectionBuilder()
//然后配置通道路由
.withUrl('/api/chatHub')
//日志信息
.configureLogging(signalR.LogLevel.Information)
//创建
.build();

var thisVue = this;
//开始连接
thisVue.connection.start();
},

 是不是很简单,只需要我们在页面初始化的时候,创建连接即可,只不过这里有一些小问题,

 咱们的项目中,已经配置好了跨域,并且所有接口也已经成功调用了,但是唯独 Hub 却不行,情况如下:

还记得上边咱们在 startup.cs 中配置的 hub 路由么,如果我们不使用 /api/chatHub 会是怎么样呢?这里我也简单把错误的给写出来,留作参考:

1、相对路径,没用代理规则:

withUrl('/axxxxx/chatHub')

640?wx_fmt=png

是因为我们用的相对路径,而且也没与代理,系统会认为我们访问的是一个页面路由,所以 404;

2、绝对路径,没用代理规则

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

 640?wx_fmt=png

这样就会出现代理的问题。

当然!如果你使用的是后端 CORS 机制跨域,不会这个问题的,其他的各种情况自己把握就好。

是不是我们这么配置好了就没事了呢,别着急,还有要给bug,

3、服务器Nginx代理

如果你在服务器里用的是 Nginx 做代理的话,可能会遇到这个问题:

640?wx_fmt=png

大家可以看看,这个错误,和上边两个都不一样,是已经连上了,但是去不能开启数据 的交互 transport !神奇,简单的看了看开源的 websockets 上提的 issues,是这么解决的《wss: Error during WebSocket handshake: Unexpected response code: 200 》

 640?wx_fmt=png

好啦!这次应该没啥问题了,继续往下走。

4、客户端调用集线器——呼叫对方

那我们现在已经连接成功了,剩下的就是调用集线器了,也就是上边我们定义的 Hub 通道,用来接收日志:

mounted() {

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

},

640?wx_fmt=png

5、从集线器调用客户端方法——接收回应

 上边我们是从客户端去订阅了一个 通道 连接,也就是说,我需要这个约定,那约定成功后,就需要接收来自服务器的通讯返回结果了,

thisVue.connection.on('ReceiveUpdate', function (update) {
console.info(
'update success!')
thisVue.tableData
= update;//将返回的数据,赋值给当前页面data
})

这个时候我们刷新页面,已经能看到消息了,然后我们在看看接口请求:

640?wx_fmt=png

是不是很熟悉!没错,这个就是我们上边说到的那个 ID ,不记得的往上看,这个是自动生成的,而且不随着消息推送而变化,只有每次请求重新连接的时候,才会变化。 

好啦,这样我们就成功了在页面上展示出了我们的数据,BUT!别慌,好像还没有完成,因为我们现在仅仅是展示了出来,还没有实现推送啊!别着急,既然一次能显示,那多次也能显示。

6、每次更新日志,推送到客户端——实时短信

这个就很简单了,我们只需要在每次日志产生的时候,来推送出来即可,举个全局异常的栗子吧:

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

 private readonly IHubContext<ChatHub> _hubContext;

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

然后直接使用:

//采用log4net 进行错误日志记录

_loggerHelper.Error(json.Message,

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


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

这样,每次我们操作的时候,就会触发生成日志的功能,同时再触发推送功能,就这样,我们把消息及时的推送了出去,达到了目的,实现了文章开头的功能。

如果想中断连接,只需要页面关闭的时候,执行 connection.stop() 即可。

 在文章开头,我说了几个场景,其他的不好实现,先来个模拟登录吧,就是把用户名密码传到后台,然后后台将结果推送回来。

具体的流程就不说了,和上边的是一样的,只是很简单的一个动作,接收下数据即可,

640?wx_fmt=gif

今天很简单的实现了两个小功能,一个是模拟登录,一个是实时推送消息,大家学会了么,这里有几个问题,大家可以思考思考:

1、SignalR到底能在平时开发中,使用哪些地方?

2、服务中心是如何将消息发出去的?

3、客户端是如何来订阅某一个通道集线器的?

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

5、如何关闭连接?

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社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 
640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316084.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Entity Framework Core访问数据库(DB2篇)

上一篇讲了一些EF Core访问Oracle的坑。&#xff08;感兴趣请移步&#xff1a;使用Entity Framework Core访问数据库&#xff08;Oracle篇&#xff09;&#xff09;这篇主要讲一下关于EF Core访问DB2的一揽子~问题。本篇采用DBFirst直接生成实体。关于EF Core DB2 的官方文档&a…

Linux中以单容器部署Nginx+ASP.NET Core

正如前文提到的&#xff0c;强烈推荐在生产环境中使用反向代理服务器转发请求到Kestrel Http服务器&#xff0c;本文将会实践将Nginx --->ASP.NET Core 部署架构容器化的过程。Nginx->ASP.NET Coe部署架构容器化在Docker中部署Nginx--->ASP.NETCore 有两种选择&#x…

领域驱动设计学习之路—DDD的原则与实践

本文是我学习Scott Millett & Nick Tune编著的《领域驱动设计模式、原理与实践》一书的学习笔记&#xff0c;一共会分为4个部分如下&#xff0c;此文为第1部分&#xff1a;领域驱动设计的原则与实践战略模式&#xff1a;在有界上下文之间通信战术模式&#xff1a;创建有效的…

.NET Core中使用Dapper操作Oracle存储过程最佳实践

为什么说是最佳实践呢&#xff1f;因为在实际开发中踩坑了&#xff0c;而且发现网上大多数文章给出的解决方法都不能很好地解决问题。尤其是在获取类型为OracleDbType.RefCursor&#xff0c;输出为&#xff1a;ParameterDirection.Output数据的时候。网上千篇一律的说写一个Ora…

CanalSharp.AspNetCore v0.0.4-支持输出到MongoDB

一、多样输出支持CanalSharp.AspNetCore是一个基于CanalSharp的适用于ASP.NET Core的一个后台任务组件&#xff0c;它可以随着ASP.NET Core实例的启动而启动&#xff0c;目前采用轮询的方式对Canal Server进行监听&#xff0c;获得MySql行更改&#xff08;RowChange&#xff09…

CF1039C Network Safety

CF1039C Network Safety 题意&#xff1a; 题解&#xff1a; 如果我们同时选中a&#xff0c;b两个点&#xff0c;无论异或什么值&#xff0c;都不会影响图的安全性&#xff0c;因为图本来就是安全的 破坏图的安全性只有一种情况&#xff0c;那就是选了a&#xff0c;没选b&…

使用Jenkins来实现内部的持续集成流程(下)

目录配置项目构建添加任务添加源代码地址和登录凭据添加构建触发器 TFS添加WebHook 添加构建步骤后端UI API端 配置项目构建1添加任务2添加源代码地址和登录凭据添加源代码地址和登录凭证此图没有填写凭证时显示的错误点击Credential后面的添加 填写能访问源代码的用户名和密码…

.NET和Docker ,比翼双飞

DockerCon 2019本周将在旧金山举行 &#xff0c;DockerCon 是从业者、贡献者、维护者、开发者和容器生态系统学习、网络和创新的一站式活动。 .NET 团队博客发布了《一起使用.NET和Docker - DockerCon 2019更新》&#xff1a;https://devblogs.microsoft.com/dotnet/using-net-…

Visible Lattice Points SPOJ - VLATTICE

Visible Lattice Points SPOJ - VLATTICE 题意&#xff1a; 有一个n∗n∗n的三维直角坐标空间&#xff0c;问从(0,0,0)看能看到几个点。 题解&#xff1a; 本题是二维的一个升级版&#xff0c;升级成三维 用莫比乌斯反演来做 代码&#xff1a; #include <bits/stdc.h…

使用ASP.NET Core开发GraphQL服务器 -- 极简预备知识(上)

为了介绍使用ASP.NET Core构建GraphQL服务器&#xff0c;本文需要介绍一下GraphQL&#xff0c;其实看官网的文档就行。什么是GraphQL&#xff1f;GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描…

使用 dotnet 命令行配合 vscode 完成一个完整 .NET 解决方案的编写和调试

如果你是开发个人项目&#xff0c;那就直接用 Visual Studio Community 版本吧&#xff0c;对个人免费&#xff0c;对小团体免费&#xff0c;不需要这么折腾。如果你是 Mac / Linux 用户&#xff0c;不想用 Visual Studio for Mac 版&#xff1b;或者不想用 Visual Studio for …

亲儿子 | Azure SignalR 服务现在支持 ASP.NET

点击上方蓝字关注“汪宇杰博客”文 / Zhidi译 / Edi Wang我们刚刚发布了支持ASP.NET的正式版 SignalR 服务 SDKMicrosoft.Azure.SignalR.AspNet v1.0.0Azure SignalR 服务是一种完全托管的用于实时消息传递的 Azure 服务。它是扩展 ASP.NET Core SignalR 应用程序的首选方法。但…

VS Code Remote 发布!开启远程开发新时代

今天&#xff08; 北京时间 2019 年 5 月 3 日 &#xff09;&#xff0c;在 PyCon 2019 大会上&#xff0c;微软发布了 VS Code Remote&#xff0c;开启了远程开发的新时代&#xff01;这次发布包含了三款核心的全新插件&#xff0c;它们可以帮助开发者在容器&#xff0c;物理或…

使用ASP.NET Core开发GraphQL服务器 -- 预备知识(下)

上一篇&#xff1a;使用ASP.NET Core开发GraphQL服务器 -- 极简预备知识(上)处理数据嵌套字段看例子&#xff1a;我想查看viewer下的repositories。注意里面的edges&#xff0c;一旦看到这个词&#xff0c;通常就表示有连接到某个数组的数据。在这里就是一个集合的repository。…

使用 Docker 在 Linux 上托管 ASP.NET Core 应用程序

说在前面在阅读本文之前&#xff0c;您必须对 Docker 的中涉及的基本概念以及常见命令有一定了解&#xff0c;本文侧重实战&#xff0c;不会对相关概念详述。同时请确保您本地开发机器已完成如下安装&#xff1a;Docker 18.06 或更高版本的 Docker 客户端.NET Core SDK 2.2 或更…

ICPC网络赛第二场G Limit

ICPC网络赛第二场G Limit 题意&#xff1a; 给你数组a和b&#xff0c;求解&#xff1a; 1≤n≤100000,−100≤ai,bi≤100,0≤t≤5.1≤n≤100000,−100≤a_{i},b_{i}≤100,0≤t≤5.1≤n≤100000,−100≤ai​,bi​≤100,0≤t≤5. 题解&#xff1a; 要用到洛必达来做&#xf…

[VSCode插件推荐] REST Client: 也许是比Postman更好的选择

在测试REST API的时候&#xff0c;想必大家都会有不同的工具选择。如果是基于CLI的话&#xff0c;大家应该会选择cURL。如果是GUI工具的话&#xff0c;相信很多人都会使用Postman。不过今天&#xff0c;笔者要推荐的是REST Client插件。也许&#xff0c;它是比Postman更好的选择…

.Net资讯 | 一大波开发者福利来了, 一份微软官方Github上发布的开源项目清单等你签收...

目录微软Github开源项目入口微软开源项目受欢迎程度排名Visual Studio CodeTypeScriptRxJS.NET Core 基础类库CNTKMicrosoft calculatorMonaco editorMS-DOSRedis windows版.NET Core CLR (公共语言运行时)ASP.NET CoreEntity Framework CorePowerShell如何在其中搜索自己需要的…

C#位运算实际作用之操作整型某一位

1.前言前几天写了两篇关于c#位运算的文章c#位运算基本概念与计算过程C#位运算实际运用在文中也提到了位运算的实际作用之一就是合并整型&#xff0c;当时引用了一个问题&#xff1a;C# 用两个short&#xff0c;一个int32拼成一个long型&#xff0c;高16位用short&#xff0c;中…

使用高性能Pipelines构建.NET通讯程序

.NET Standard支持一组新的API&#xff0c;System.Span, System.Memory&#xff0c;还有System.IO.Pipelines。这几个新的API极大了提升了.NET程序的效能&#xff0c;将来.NET很多基础API都会使用它们进行重写。Pipelines旨在解决.NET编写Socket通信程序时的很多困难&#xff0…