使用ABP SignalR重构消息服务(一)
使用ABP SignalR重构消息服务
最近协助蟹老板升级新框架,维护基础设施服务,目前已经稳了。
早上蟹老板看到我进入公司,马上就叫停我,说我为什么左脚先进公司,你这样会让我很难做耶,这样把我给你一次机会把现在的消息服务重构了,我就放过你这一次。(当时我都没有反应过来,蟹老板就准备和我讲需求了,我赶紧着小本子开始记需求)

背景
我们需要记录所有用户的在线状况(登录的设备存在多个设备同时登录) 、指定用户下线 、实时接收消息技术你可以自由技术发挥,今天中午之前给我一个设计概要。(呜呜,天空是蔚蓝色、窗外还有千纸鹤)
技术点
- SignalR
SignalR 是一个开放源代码库,可用于简化向应用添加实时 Web 功能。 实时 Web 功能使服务器端代码能够将内容推送到客户端。 - Redis
Redis 是一个开源(BSD 许可)的内存数据结构存储,用作数据库、缓存和消息代理。 - Jwt
JSON Web Token (JWT) 是一个开放标准 ( RFC 7519 ),它定义了一种紧凑且自包含的方式,用于在各方之间以 JSON 对象的形式安全传输信息。此信息可以验证和信任,因为它是数字签名的。JWT 可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
为什么使用SignalR
ASP.NET Core SignalR 的一些功能
- 自动处理连接管理。
- 同时向所有连接的客户端发送消息。 例如聊天室。
- 向特定客户端或客户端组发送消息。
- 对其进行缩放,以处理不断增加的流量。
SignalR支持如下的方式实现实时通信(SignalR会自动选择服务器和客户端能力范围内的最佳通信方式)
- WebSockets:是一种在单个TCP连接上进行全双工通信的协议,使得服务器和浏览器的通信更加简单,服务端可以主动发送信息。
- Server-Sent Events:SSE 与 WebSocket 作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息。WebSocket是双向的,而SSE是单向的。
- Long Polling(长轮询) :和传统的轮询原理一样,只是服务端不会每次都返回响应信息,只有有数据或超时了才会返回,从而减少了请求次数。
SignalR核心
Hub 是一种高级管道,允许客户端和服务器相互调用方法。 SignalR 自动处理跨计算机边界的调度,并允许客户端调用服务器上的方法,反之亦然。 可以将强类型参数传递给方法,从而支持模型绑定。 SignalR 提供两种内置中心协议:基于 JSON 的文本协议和基于 SignalR 的二进制协议。 与 JSON 相比,MessagePack 通常会创建更小的消息。 旧版浏览器必须支持 XHR 级别 2 才能提供 MessagePack 协议支持。
中心通过发送包含客户端方法的名称和参数的消息来调用客户端代码。 作为方法参数发送的对象使用配置的协议进行反序列化。 客户端尝试将名称与客户端代码中的方法匹配。 当客户端找到匹配项时,它会调用该方法并将反序列化的参数数据传递给它。
Hubs(集线器)介绍
- Hub.Context
Hub 类具有一个 Context 属性,该属性包含具有连接相关信息的以下属性
| 属性 | 说明 |
|---|---|
| ConnectionId | 获取连接的唯一 ID(由 SignalR 分配)。 每个连接有一个连接 ID。 |
| UserIdentifier | 获取用户标识符。 默认情况下,SignalR 使用与连接关联的 ClaimsPrincipal 中的 ClaimTypes.NameIdentifier 作为用户标识符。 |
| User | 获取与当前用户关联的 ClaimsPrincipal。 |
| Items | 获取可用于在此连接范围内共享数据的键/值集合。 数据可以存储在此集合中,会在不同的中心方法调用间为连接持久保存。 |
| Features | 获取连接上可用的功能的集合。 目前,在大多数情况下不需要此集合,因此未对其进行详细记录。 |
| ConnectionAborted | 获取一个 CancellationToken,它会在连接中止时发出通知。 |
Hub.Context还包含以下方法
| 方法 | 说明 |
|---|---|
| GetHttpContext | 返回连接的 HttpContext,如果连接不与 HTTP 请求关联,则返回 null。 对于 HTTP 连接,可以使用此方法获取 HTTP 标头和查询字符串等信息。 |
| Abort | 中止连接。 |
- Hub.Clients
Hub 类具有一个 Clients 属性,该属性包含适用于服务器与客户端之间的通信的以下属性
| 属性 | 说明 |
|---|---|
| All | 对所有连接的客户端调用方法 |
| Caller | 对调用了中心方法的客户端调用方法 |
| Others | 对所有连接的客户端调用方法(调用了方法的客户端除外) |
Hub.Clients还包含以下方法
| 方法 | 说明 |
|---|---|
| AllExcept | 对所有连接的客户端调用方法(指定连接除外) |
| Client | 对连接的一个特定客户端调用方法 |
| Clients | 对连接的多个特定客户端调用方法 |
| Group | 对指定组中的所有连接调用方法 |
| GroupExcept | 对指定组中的所有连接调用方法(指定连接除外) |
| Groups | 对多个连接组调用方法 |
| OthersInGroup | 对一个连接组调用方法(不包括调用了中心方法的客户端) |
| User | 对与一个特定用户关联的所有连接调用方法 |
| Users | 对与多个指定用户关联的所有连接调用方法 |
设计思路
使用SignalR与客户端进行实时通讯、用户链接管理、JWt进行用户身份认证和鉴权、Redis保存用户链接信息
- 前端创建链接之后就会触发后端
OnConnectedAsync()方法,这样我们就可以通过获取当前的连接IP信息和用户浏览器信息组成一个唯一设备标识。 - 我们创建一个Redis key数据类型为
Hashes将用户Id当成key,然后将不同设备登录用户当成value存储。 - 反之当用户主动断开链接、或者关闭浏览器就会触发后端
OnDisconnectedAsync()方法,就代表该设备的用户下线了。
前端设计
与服务端创建链接
前端使用@aspnet/signalr与服务端进行握手通讯,用户登录成功建立一个Socket链接
// 创建链接
this.init.connection = new signalR.HubConnectionBuilder()
// IM_URL链接地址
.withUrl(IM_URL, {
// accessTokenFactory携带用户Token进行身份认证和鉴权
accessTokenFactory: () => this.token
}).build();
监听关闭事件
方式客户端发生意外断线,或者后端断开我们的链接,我们就可以监听关闭事件,给到用户一些提示
this.init.connection.onclose(function() {
console.log('connecition closed');
});
接收消息(画重点)
因为我自己写过一个IM的小应用,自己就也写过前端,所以这里我会给一些经验给到前端大佬。
思路是这样的:前端程序初始化Signalr接收消息方法的时候带一个参数(类似委托的参数),这个委托是一个消息类型处理工厂。
App.Vue 文件中的代码
methods: {
// 接受用户信息进入消息总线
ReceiveUserMsg(data) {
....处理消息工厂代码.....
switch (switch_on)
{
case "消息类型" :
break;
}
}},
created() {
try {
// 初始化创建链接
this.$signalr.CreatorConnectServer();
// 初始化用户消息接收
this.$signalr.ReUserReceiveMessage(this.ReceiveUserMsg);
// 初始化链接关闭事件
this.$signalr.OnClose();
} catch (e) {
console.log("网络错误");
}}
signalr.js(自己专门封装的一个js)
// 接受信息
ReUserReceiveMessage(receiveUserMsg) {
this.init.connection.on("ReUserReceiveMessage", (result) => {
// 执行委托
receiveUserMsg(result);
console.log(result)
});
}
使用ABP SignalR重构消息服务(一)的更多相关文章
- 使用ABP SignalR重构消息服务(二)
使用ABP SignalR重构消息服务(二) 上篇使用ABP SignalR重构消息服务(一)主要讲的是SignalR的基础知识和前端如何使用SignalR,这段时间也是落实方案设计.这篇我主要讲解S ...
- 基于SignalR的消息推送与二维码描登录实现
1 概要说明 使用微信扫描登录相信大家都不会陌生吧,二维码与手机结合产生了不同应用场景,基于二维码的应用更是比较广泛.为了满足ios.android客户端与web短信平台的结合,特开发了基于Singl ...
- X-Admin&ABP框架开发-消息通知
业务型网站使用过程中,消息通知是一个不可或缺的功能,采用站内通知.短信通知.邮件通知.微信通知等等各种方式都有,ABP框架对这部分工作已经封装的很好了,站在巨人的肩膀上,一览全貌,带来的就是心情舒畅. ...
- AngularJS+ASP.NET MVC+SignalR实现消息推送
原文:AngularJS+ASP.NET MVC+SignalR实现消息推送 背景 OA管理系统中,员工提交申请单,消息实时通知到相关人员及时进行审批,审批之后将结果推送给用户. 技术选择 最开始发现 ...
- 实时显示数据 SignalR 及时消息提醒( 立即向其推送内容)
实时显示数据 SignalR 及时消息提醒( 立即向其推送内容) http://www.cnblogs.com/Leo_wl/p/5634910.html <!--Reference the ...
- Signalr实现消息推送
一.前言 大多数系统里面好像都有获取消息的功能,但这些消息来源都不是实时的,比如你开两个浏览器,用两个不同的账号登录,用一个账号给另外一个账号发送消息,然而并不会实时收到消息,必须要自己手动F5刷新一 ...
- [2017-10-25]Abp系列——集成消息队列功能(基于Rebus.Rabbitmq)
本系列目录:Abp介绍和经验分享-目录 前言 由于提交给ABP作者的集成消息队列机制的PR还未Review完成,本篇以Abplus中的代码为基准来介绍ABP集成消息队列机制的方案. Why 为什么需要 ...
- 消息服务MNS和消息队列ONS产品对比
消息服务MNS和消息队列ONS产品对比 MNS已经进过严格测试,已达到商业化的稳定性要求,其主要特点和适用场景 1.数据高可靠(10个9),对于数据可靠性敏感(要求消息数据不丢)的应用场景建议选择. ...
- JMS(Java消息服务)入门教程
什么是Java消息服务 Java消息服务指的是两个应用程序之间进行异步通信的API,它为标准消息协议和消息服务提供了一组通用接口,包括创建.发送.读取消息等,用于支持JAVA应用程序开发.在J2EE中 ...
随机推荐
- Solution -「LOCAL」充电
\(\mathcal{Description}\) 给定 \(n,m,p\),求序列 \(\{a_n\}\) 的数量,满足 \((\forall i\in[1,n])(a_i\in[1,m])\l ...
- 探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器?
探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器? 探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器? 线上多个服务应用陷入了死 ...
- 详解Spring DI循环依赖实现机制
一个对象引用另一个对象递归注入属性即可实现后续的实例化,同时如果两个或者两个以上的 Bean 互相持有对⽅,最终形成闭环即所谓的循环依赖怎么实现呢属性的互相注入呢? Spring bean生命周期具体 ...
- Centos下Ambari2.7.5的编译和安装
前言 终于,要开始写点大数据相关的文章了.当真的要开始写老本行的时候,还是考虑了挺久的.一是不知道从何处写起,二是如何能写点有意思的. 我们常说,过程比结果重要.也是有很多人喜欢准备完全之后,才会开始 ...
- python进阶(25)协程
协程的定义 协程(Coroutine),又称微线程,纤程.(协程是一种用户态的轻量级线程) 作用:在执行 A 函数的时候,可以随时中断,去执行 B 函数,然后中断B函数,继续执行 A 函数 (可以自动 ...
- 【Python自动化Excel】pandas操作Excel的“分分合合”
话说Excel数据表,分久必合.合久必分.Excel数据表的"分"与"合"是日常办公中常见的操作.手动操作并不困难,但数据量大了之后,重复性操作往往会令人崩溃. ...
- Zabbix 6.0:原生高可用(HA)方案部署
Blog:博客园 个人 本部署文档适用于CentOS 8.X/RHEL 8.X/Anolis OS 8.X/AlmaLinux 8.X/Rockey Linux 8.X. 原生的HA方案终于来了 相比 ...
- Objective-C 基础教程第三章,面向对象编程基础知
目录 Objective-C 基础教程第三章,面向对象编程基础知 0x00 前言 0x01 间接(indirection) 0x02 面向对象编程中使用间接 面向过程编程 面向对象编程 0x03 OC ...
- 017 Linux 之啥是 ssh ?
1 什么是 ssh?有什么用? (1)ssh 是一种协议 SSH(Secure Shell) 是较可靠,专为远程登录会话和其他网络服务提供安全性的协议,利用 SSH 协议可以有效防止远程管理过程中的信 ...
- .NET6: 开发基于WPF的摩登三维工业软件 (7)
做为一个摩登的工业软件,提供可编程的脚本能力是必不可少的能力.脚本既可以方便用户进行二次开发,也对方便对程序进行自动化测试.本文将结合AnyCAD对Python脚本支持的能力和WPF快速开发带脚本编辑 ...