使用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重构消息服务(一)的更多相关文章

  1. 使用ABP SignalR重构消息服务(二)

    使用ABP SignalR重构消息服务(二) 上篇使用ABP SignalR重构消息服务(一)主要讲的是SignalR的基础知识和前端如何使用SignalR,这段时间也是落实方案设计.这篇我主要讲解S ...

  2. 基于SignalR的消息推送与二维码描登录实现

    1 概要说明 使用微信扫描登录相信大家都不会陌生吧,二维码与手机结合产生了不同应用场景,基于二维码的应用更是比较广泛.为了满足ios.android客户端与web短信平台的结合,特开发了基于Singl ...

  3. X-Admin&ABP框架开发-消息通知

    业务型网站使用过程中,消息通知是一个不可或缺的功能,采用站内通知.短信通知.邮件通知.微信通知等等各种方式都有,ABP框架对这部分工作已经封装的很好了,站在巨人的肩膀上,一览全貌,带来的就是心情舒畅. ...

  4. AngularJS+ASP.NET MVC+SignalR实现消息推送

    原文:AngularJS+ASP.NET MVC+SignalR实现消息推送 背景 OA管理系统中,员工提交申请单,消息实时通知到相关人员及时进行审批,审批之后将结果推送给用户. 技术选择 最开始发现 ...

  5. 实时显示数据 SignalR 及时消息提醒( 立即向其推送内容)

    实时显示数据  SignalR 及时消息提醒( 立即向其推送内容) http://www.cnblogs.com/Leo_wl/p/5634910.html  <!--Reference the ...

  6. Signalr实现消息推送

    一.前言 大多数系统里面好像都有获取消息的功能,但这些消息来源都不是实时的,比如你开两个浏览器,用两个不同的账号登录,用一个账号给另外一个账号发送消息,然而并不会实时收到消息,必须要自己手动F5刷新一 ...

  7. [2017-10-25]Abp系列——集成消息队列功能(基于Rebus.Rabbitmq)

    本系列目录:Abp介绍和经验分享-目录 前言 由于提交给ABP作者的集成消息队列机制的PR还未Review完成,本篇以Abplus中的代码为基准来介绍ABP集成消息队列机制的方案. Why 为什么需要 ...

  8. 消息服务MNS和消息队列ONS产品对比

    消息服务MNS和消息队列ONS产品对比 MNS已经进过严格测试,已达到商业化的稳定性要求,其主要特点和适用场景 1.数据高可靠(10个9),对于数据可靠性敏感(要求消息数据不丢)的应用场景建议选择. ...

  9. JMS(Java消息服务)入门教程

    什么是Java消息服务 Java消息服务指的是两个应用程序之间进行异步通信的API,它为标准消息协议和消息服务提供了一组通用接口,包括创建.发送.读取消息等,用于支持JAVA应用程序开发.在J2EE中 ...

随机推荐

  1. tabbar选中按钮的标题颜色和字体

    @implementation XMGTabBarController /* 问题: 1.选中按钮的图片被渲染 -> iOS7之后默认tabBar上按钮图片都会被渲染 1.修改图片 2.通过代码 ...

  2. Linux 内核引导参数简介

    概述 内核引导参数大体上可以分为两类:一类与设备无关.另一类与设备有关.与设备有关的引导参数多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导参数.比如,如果你想知道可以向 AHA ...

  3. 通过安装HomeBrew来安装Python3

    首先说什么是HomeBrew? 下面引用简书上一个博客的解释:(博客链接:http://www.jianshu.com/p/d229ac7fe77d) 为什么要使用Homebrew Mac OS X是 ...

  4. ssh一段时间无操作后自动断开连接(假死)问题

    平时使用ssh远程服务器的时候(注:远程虚拟机一般不会有这个问题),一段时间没有操作,ssh连接就会处于假死状态,以至于需要重新进行ssh连接,不管你用的什么远程工具都会出现这个问题,那么通过心跳检测 ...

  5. 12、Linux基础--挂载磁盘步骤、流处理工具awk(正则 比较 逻辑 算数表达式 流程控制)

    笔记 1.晨考 1.用两种方法,实现将文件中的以# 开头的行把# 去掉 sed -r 's/^#//g' /etc/fstab cat /etc/fstab | tr -d '^#' 2.将文件中的H ...

  6. MyBatis功能点二:MyBatis提供的拦截器平台

    前面关于MyBatis功能点二plugin已经介绍了一些应用及其实现的底层代码,本文总结MyBatis提供的拦截器平台框架体系. 通过MyBatis功能点二:从责任链设计模式的角度理解插件实现技术 - ...

  7. [LeetCode]771. 宝石与石头

    给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头. S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石. J 中的字母不重复,J 和 S中的所有字符都是字母 ...

  8. python-xlutils模块-修改excel

    前言 xlrd库用于读取excel文件中的数据,xlwt库用于将数据写入excel文件,修改用xlutils模块: xlutils库也仅仅是通过复制一个副本进行操作后保存一个新文件,像是xlrd库和x ...

  9. 三行Python代码,让你的数据处理脚本快别人4倍

    Python是一门非常适合处理数据和自动化完成重复性工作的编程语言,我们在用数据训练机器学习模型之前,通常都需要对数据进行预处理,而Python就非常适合完成这项工作,比如需要重新调整几十万张图像的尺 ...

  10. Thread、ThreadPool 和 Task

    对 C# 开发者来说,不可不理解清楚 Thread.ThreadPool 和 Task 这三个概念.这也是面试频率很高的话题,在 StackOverflow 可以找到有很多不错的回答,我总结整理了一下 ...