[重磅开源] 比SingleR更适合的websocket 即时通讯组件---ImCore开源了
有感而发
为什么说 SignalR 不合适做 IM?
IM 的特点必定是长连接,轮训的功能用不上。
因为它是双工通讯的设计,用hub.invoke发送命令给服务端处理业务,其他就和 ajax 差不多,用来代替 ajax 减少 http 请求数量比较看好。
但是过多使用 hub,SignalR 服务端会被业务入侵严重,业务变化频繁后不得不重新发布版本,每次部署所有终端都会断开连接,遇到5分钟发一次业务补丁的时候,类似离线和上线提示好友的功能就无法实现。
ImCore 的设计是业务和推送分离,即 ImServer 永不更新重启,业务全部在 webApi 上编写,终端连接的 ImServer 就不会频繁重启的问题。
为什么说又呢?
熟悉叶先森的朋友应该都知道,他之前开源了两款比较热门的组件,如:
CSRedisCore: 操作Redis的简单易用的组件。GitHub:https://github.com/2881099/csredis 目前也已经八百多星了,nuget下载量也已经121k了.相关介绍及使用可以参考《.NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐》
FreeSql:FreeSql 是一个功能强大的对象关系映射程序(O/RM),支持 .NETCore 2.1+ 或 .NETFramework 4.5+。这个可以说是比EFCore更好用的一个ORM组件了。这个组件目前也已经有八百多星了,nuget下载量也已经13.9k了。GitHub地址:https://github.com/2881099/FreeSql 。据说用了这个组件后头发都茂密了起来。
而且上面两个组件我也一直在用,感觉很方便。有兴趣的小伙伴可以.net core两千人群交流讨论:637326624
ImCore是什么
ImCore是一个利用 WebSocket 实现简易、高性能、集群化部署的即时通讯组件,支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。
Quick Start
dotnet add package ImCore
IM服务端
public void Configure(IApplicationBuilder app)
{
app.UseImServer(new ImServerOptions
{
Redis = new CSRedis.CSRedisClient("127.0.0.1:6379,poolsize=5"),
Servers = new[] { "127.0.0.1:6001" }, //集群配置
Server = "127.0.0.1:6001"
});
}
一套永远不需要迭代更新的IM服务端
WebApi业务端
public void Configure(IApplicationBuilder app)
{
//...
ImHelper.Initialization(new ImClientOptions
{
Redis = new CSRedis.CSRedisClient("127.0.0.1:6379,poolsize=5"),
Servers = new[] { "127.0.0.1:6001" }
});
ImHelper.EventBus(
t => Console.WriteLine(t.clientId + "上线了"),
t => Console.WriteLine(t.clientId + "下线了"));
}
| ImHelper方法 | 参数 | 描述 |
|---|---|---|
| PrevConnectServer | (clientId, string) | 在终端准备连接 WebSocket 前调用 |
| SendMessage | (发送者, 接收者, 消息内容, 是否回执) | 发送消息 |
| GetClientListByOnline | - | 返回所有在线clientId |
| EventBus | (上线委托, 离线委托) | socket上线与下线事件 |
| 群聊频道 | 参数 | 描述 |
|---|---|---|
| JoinChan | (clientId, 频道名) | 加入 |
| LeaveChan | (clientId, 频道名) | 离开 |
| GetChanClientList | (频道名) | 获取群聊频道所有clientId |
| GetChanList | - | 获取所有群聊频道和在线人数 |
| GetChanListByClientId | (clientId) | 获取用户参与的所有群聊频道 |
| GetChanOnline | (频道名) | 获取群聊频道的在线人数 |
| SendChanMessage | (clientId, 频道名, 消息内容) | 发送群聊消息,所有在线的用户将收到消息 |
说明:clientId 应该与 webApi的用户id相同,或者有关联。
Html5终端
本方案支持集群分区,前端连接 websocket 前,应该先请求 webApi 获得地址(ImHelper.PrevConnectServer)。
运行示例
运行环境:.NETCore 2.1 + redis-server 2.8
下载Redis-x64-2.8.2402.zip,点击 start.bat 运行;
cd imServer && dotnet run
cd web && dotnet run
打开多个浏览器,访问 http://127.0.0.1:5000 发送群消息

设计思路
ImServer 是 websocket 服务中心,可部署多实例,按clientId分区管理socket连接;
webApi 或其他应用端,使用 ImHelper 调用相关方法(如:SendMessage、群聊相关方法);
消息发送利用了 redis 订阅发布技术。每个 imServer 订阅相应的频道,收到消息,指派 websocket 向终端(如浏览器)发送消息;
1、可缓解并发推送消息过多的问题;
2、可解决连接数过多的问题;
客户端连接流程:client -> websocket -> imserver
imserver 订阅消息:client <- imserver <- redis channel
推送消息流程:web1 -> sendmsg方法 -> redis channel -> imserver
imserver 充当消息转发,及维护连接中心,代码万年不变不需要重启维护;
WebSocket
比较笨的办法是浏览器端使用websocket,其他端socket,这种混乱的设计非常难维护。
强烈建议所有端都使用websocket协议,websocket协议支持几乎所有端,adorid/ios/h5/小程序全部支持websocket客户端。
websocket用了后,就像跨平台。。。虽然选一种语言都能连接通讯。
业务与通讯协议
im系统一般涉及【我的好友】、【我的群】、【历史消息】等等。。
那么,imServer与业务方(webApi)该保持何种关系呢?
用户A向好友B发送消息,分析一下:
- 需要判断B是否为A好友;
- 需要判断A是否有权限;
- 等等。。
诸如此类业务判断会很复杂,我们试想一下,如果使用imServer做业务协议,它是不是会变成巨无霸难以维护?
又比如获取历史聊天记录,难道客户端要先websocket.send('gethistory'),再在onmessage里定位回调处理?
我们可以这样设定,所有用户的主动行为走业务方(webApi),imServer只负责即时消息推送。什么意思?
用户A向好友B发送消息:客户端请求业务方(webApi)接口,由业务方(webApi)后端向imServer发起推送请求,imServer收到指令后,向前端用户B的websocket发送数据,用户B收到了消息。
获取历史消息:客户端请求业务方(webApi)接口,返回json(历史消息)
回执:用户A如何知道消息发送状态(成功或失败或不在线)?imServer端向用户B发送消息时,把状态以消息的方式推给用户A即可(按上面的逻辑),具体请看源码吧。。。
发送消息
业务和推送分离的设计,即 imServer 只负责推送工作。
用户A向B发消息:终端A ajax -> webApi -> imServer -> 终端B WebSocket.onmessage;
采用 redis 轻量级的订阅发布功能,实现消息缓冲发送。
redis 缓冲消息发送,避免对业务方(webApi)造成消息发送的性能损耗,属于必备,也可以更换为其他技术。
比如 webapi 业务发需要通知1000个人,不用消息缓冲的话。。。
还有使用redis存储一些数据,如在线clientId,群聊结构。
集群分区
单个imServer实例支持多少个客户端连接,两千个没问题?
如果在线用户有10万人,怎么办???
比如部署4个imServer:
imServer1 订阅 redisChanne1
imServer2 订阅 redisChanne2
imServer3 订阅 redisChanne3
imServer4 订阅 redisChanne4
业务方(webApi)端根据接收方的clientId后四位16进制与节点总数取模,定位到对应的redisChannel,进行redis->publish操作将消息定位到相应的imServer。
每个 imServer 管理着对应的终端连接,当接收到 redis 订阅消息后,向对应的终端连接推送数据。
事件消息
IM 系统比较常用的有上线、下线,在 imServer 层才能准确捕捉事件,但业务代码就不合适在这上面编写了。
采用 redis 发布订阅技术,将上线、下线等事件向指定频道发布,业务方(webApi) 通过 ImHelper.EventBus 方法进行订阅捕捉。

A向B发文件的例子
1、A向webapi传文件
2、webapi告诉imServer,A向B正在传文件
3、B收到消息,A正在传文件
4、webapi文件接收完成时告诉imServer,A向B文件传输完毕
5、B收到消息,A文件传输完成(含文件链接)
[重磅开源] 比SingleR更适合的websocket 即时通讯组件---ImCore开源了的更多相关文章
- [开源] .NETCore websocket 即时通讯组件---ImCore
前言 ImCore 是一款 .NETCore 下利用 WebSocket 实现的简易.高性能.集群即时通讯组件,支持点对点通讯.群聊通讯.上线下线事件消息等众多实用性功能. 开源地址:https:// ...
- Springboot 项目源码 Activiti6 工作流 vue.js html 跨域 前后分离 websocket即时通讯
特别注意: Springboot 工作流 前后分离 + 跨域 版本 (权限控制到菜单和按钮) 后台框架:springboot2.1.2+ activiti6.0.0+ mybaits+maven+接 ...
- java SSM框架 代码生成器 快速开发平台 websocket即时通讯 shiro redis
A代码编辑器,在线模版编辑,仿开发工具编辑器,pdf在线预览,文件转换编码 B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 , ...
- 使用tomcat方式实现websocket即时通讯服务端讲解
使用tomcat方式实现websocket即时通讯服务端讲解 第一种方案:使用Tomcat的方式实现 tomcat版本要求:tomcat7.0+.需要支持Javaee7 导入javeee-api的ja ...
- XyTalk企业即时通讯IM开始开源
网址: https://gitee.com/475660/xyTalk-pc https://github.com/xy-Group/xyTalk-pc Xy.Platform是一个高性能.可扩展的企 ...
- java SSM 框架 多数据源 代码生成器 websocket即时通讯 shiro redis 后台框架源码
A 调用摄像头拍照,自定义裁剪编辑头像 [新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统]B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,开发利器)+快速构建表单; 技 ...
- java ssm 后台框架平台 项目源码 websocket 即时通讯 IM quartz springmvc
官网 http://www.fhadmin.org/D 集成安全权限框架shiro Shiro 是一个用 Java 语言实现的框架,通过一个简单易用的 API 提供身份验证和授权,更安全,更可靠E ...
- java SSM 框架 代码生成器 websocket即时通讯 shiro redis
1. 权限管理:点开二级菜单进入三级菜单显示 角色(基础权限)和按钮权限 角色(基础权限): 分角色组和角色,独立分配菜单权限和增删改查权限. 按钮权限: 给角色分配按钮权限. ...
- HTML5+NodeJs实现WebSocket即时通讯
声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢! 最近都在学习HTML5,做canvas游戏之类的,发现HTML5中除了canvas这个强大的工具外,还有WebSocket也很值得注意.可 ...
随机推荐
- Spark学习之路(八)—— Spark SQL 之 DataFrame和Dataset
一.Spark SQL简介 Spark SQL是Spark中的一个子模块,主要用于操作结构化数据.它具有以下特点: 能够将SQL查询与Spark程序无缝混合,允许您使用SQL或DataFrame AP ...
- 系统学习 Java IO (十三)----字符读写 Reader/Writer 及其常用子类
目录:系统学习 Java IO---- 目录,概览 Reader Reader 类是 Java IO API 中所有 Reader 子类的基类. Reader 类似于 InputStream ,除了它 ...
- mysql-8.0-winx64安装以及修改密码
一.下载安装包(https://dev.mysql.com/downloads/mysql/) 二.添加my.ini配置文件 打开刚刚解压的文件夹 C:\mysql-8.0.16-winx64,在该文 ...
- hdoj1009 FatMouse' Trade——贪心算法
贪心思路:按单位猫粮能兑换到的javaBean从大到小将组合进行排序,总是在当前兑换尽可能多的javabeans 问题描述:点击打开链接 hdoj1009 FatMouse's Trade 源代码: ...
- ES5_05_Function扩展
Function 构造器的语法: 注意: 参数 arg1 , arg2 , argN 被函数使用的参数的名称必须是合法命名的.参数名称是一个有效的JavaScript标识符的字符串,或者一个用逗号分隔 ...
- 并发编程-concurrent指南-交换机Exchanger
java.util.concurrent包中的Exchanger类可用于两个线程之间交换信息.可简单地将Exchanger对象理解为一个包含两个格子的容器,通过exchanger方法可以向两个格子中填 ...
- 从同步原语看非阻塞同步以及Java中的应用
非阻塞同步:基于冲突检测的乐观并发策略,通俗讲就是先进行操作,如果没有其他线程争用共享数据,那操作就成功了,如果争用数据有冲突那就采用其他的补偿措施(最常见的就是不断重试直到成功),这种乐观的并发策略 ...
- 西门子S7-1200与 G120系列变频器USS通信
西门子S7-1200 紧凑型PLC在当前的市场中有着广泛的应用,作为经常与SINAMICS G120系列变频器共同使用的PLC,其USS通信协议的使用一直在市场上有着非常广泛的应用.本文将主要介绍如何 ...
- c++学习书籍推荐《深度探索C++对象模型》下载
百度云及其他网盘下载地址:点我 百度云及其他网盘下载地址:点我 编辑推荐 如果你是一位C++程序员,渴望对于底层知识获得一个完整的了解,那么这本<深度探索C++对象模型>正适合你 作者简介 ...
- c#零碎知识随笔
1. 字符串转换日期: DateTime.ParseExact(item.Attribute("event-timestamp").Value,"dd.MM.yyyy H ...