[重磅开源] 比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也很值得注意.可 ...
随机推荐
- 对def函数的参数认识
转载:https://www.cnblogs.com/Guido-admirers/p/6068702.html 如何理解函数的形式参数*args,**kwargs 形参*args的输出形式为tupl ...
- vagramt中同步文件,webpack不热加载
这是一篇参考文章:https://webpack.js.org/guides/development-vagrant/ 在使用vue-cli+webpack构建的项目中,如何使用vagrant文件同步 ...
- memcached--delete--replace--set--get--incr--decr--stats
memcached命令 1.get key 来获取在内存中的值 get name 2.delete key 删除在内存中的值 delete name 3.replace key flag exp ...
- Apache配置URL重定向
Apache配置URL重定向 修改/etc/httpd/conf/httpd.conf文件的内容 <Directory "/var/www"> AllowOverrid ...
- 基于百度云的OCR识别(Python)
2019年7月3日早上,在百度AI开发者大会上,一个来自山西的青年,将一瓶矿泉水浇在了同样来自山西的李彦宏身上. 可以回顾一下 https://b23.tv/av57665929/p1 ,着实让人一惊 ...
- Python连载20-偏函数&zip函数&enumerate函数
一. 偏函数 二. #先举个例子 #把字符串转换为十进制数字 int(') #help(int),int函数中有一个参数base代表把它转换某个进制的数字 #把八进制的字符串转换为十进制 eight ...
- CRISP-DM--数据挖掘标准流程
CRISP-DM--数据挖掘标准流程 在1996年的时候,SPSS,戴姆勒-克莱斯勒和NCR公司发起共同成立了一个兴趣小组,目的是为了建立数据挖掘方法和过程的标准.并在1999年正式提炼出了CRISP ...
- CSS3文本与字体
一.CSS3 换行 1.word-break(规定自动换行的处理方法) word-break: normal / break-all / keep-all; /* normal:使用浏览器默认的换行规 ...
- 玩转SpringBoot之整合Mybatis拦截器对数据库水平分表
利用Mybatis拦截器对数据库水平分表 需求描述 当数据量比较多时,放在一个表中的时候会影响查询效率:或者数据的时效性只是当月有效的时候:这时我们就会涉及到数据库的分表操作了.当然,你也可以使用比较 ...
- leetcode 141 Linked List Cycle Hash fast and slow pointer
Problem describe:https://leetcode.com/problems/linked-list-cycle/ Given a linked list, determine if ...