热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[开源].NETCorewebsocket即时通讯组件ImCore

ImCore利用webSocket协议实现简易、高性能、集群即时通讯组件,支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。QuickStartdotne

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),伪代码:

ajax(\'/prev-connect-imserver\', function(data) {
    var url = data; //此时的值:ws://127.0.0.1:6001/ws?token=xxxxx
    var sock = new WebSocket(url);
    sock.Onmessage= function (e) {
        //...
    };
})

Demo

运行环境:.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 发送群消息

image

设计思路

终端(如浏览器) 使用 webSocket 连接 imServer;

imServer 根据 clientId 分区管理 webSocket 连接,可群集部署;

webApi 或其他应用端,使用 ImHelper 调用相关方法(如:SendMessage、群聊相关方法),将数据推至 Redis Channel;

imServer 订阅 Redis Channel,收到消息后向终端(如浏览器)推送消息;

1、可缓解并发推送消息过多的问题;

2、可解决连接数过多的问题;

3、解决业务和通讯分离,结构更加清淅;

imServer 充当消息转发,维护连接,代码万年不变不需要重启维护

webApi 负责所有业务

webSocket

如果浏览器使用 webSocket ,iOS 使用其他协议,协议不一致的后果很严重(难维护)。

建议所有端都使用 webSocket 协议,adorid/ios/h5/小程序 全部支持 webSocket 客户端。

业务通讯

IM 系统一般涉及【我的好友】、【我的群】、【历史消息】等等。。

那么,imServer与业务方(webApi)该保持何种关系呢?

用户A向好友B发送消息,分析一下:

  • 需要判断B是否为A好友;
  • 需要判断A是否有权限;
  • 等等。。

诸如此类业务判断会很复杂,如果使用imServer做业务协议,它是不是会变成巨无霸难以维护?

又如获取历史聊天记录,难道客户端要先webSocket.send(\'gethistory\'),再在onmessage里定位回调处理?

发送消息

业务和推送分离的设计,即 imServer 只负责推送工作,webApi 负责业务。

用户A向B发消息:终端A ajax -> webApi -> imServer -> 终端B webSocket.onmessage;

获取历史消息:客户端请求业务方(webApi)接口,返回json(历史消息)。

背后采用 redis 轻量级的订阅发布功能,实现消息缓冲发送,方案必备之一,后期可更换为其他技术。比如 webApi 业务发需要通知1000个人,若不用消息缓冲,会对 webApi 应用程序整体将造成性能损耗。

还有使用 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 方法进行订阅捕捉。

image

A向B发文件的例子

1、A向 webapi 传文件

2、webapi 告诉 imServer,A向B正在传文件,ImHelper.SendMessage(B, "A正在给传送文件...")

3、B收到消息,A正在传文件

4、webapi 文件接收完成时告诉imServer,A向B文件传输完毕,ImHelper.SendMessage(B, "A文件传输完毕(含文件链接)")

5、B收到消息,A文件传输完毕(含文件链接)

有感而发

为什么说 signalr 不合适做 im?

im 的特点必定是长连接,轮训的功能用不上。

因为他是双工通讯的设计,用 hub.invoke 发送命令给服务端处理业务,其他就和 ajax 差不多,用来代替 ajax 减少 http 请求数量比较看好。

但是过多使用 hub,signalr 服务端会被业务入侵严重,业务变化频繁后不得不重新发布版本,每次部署所有终端都会断开连接,遇到5分钟发一次业务补丁的时候,类似离线和上线提示好友的功能就无法实现。

ImCore 的设计是业务和推送分离,即 imServer 永不更新重启,业务全部在 webApi 上编写,终端连接的是 imServer 就不会频繁重启的问题。


推荐阅读
  • 工作经验谈之-让百度地图API调用数据库内容 及详解
    这段时间,所在项目中要用到的一个模块,就是让数据库中的内容在百度地图上展现出来,如经纬度。主要实现以下几点功能:1.读取数据库中的经纬度值在百度上标注出来。2.点击标注弹出对应信息。3 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 这篇文章给大家讲解如何利用dhtmlxGantt在服务器端集成数据。脚本数据保存如果您已初始化dataProcessor,则用户或以编程方式所做的任何更改都将自动 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 本文介绍了Java后台Jsonp处理方法及其应用场景。首先解释了Jsonp是一个非官方的协议,它允许在服务器端通过Script tags返回至客户端,并通过javascript callback的形式实现跨域访问。然后介绍了JSON系统开发方法,它是一种面向数据结构的分析和设计方法,以活动为中心,将一连串的活动顺序组合成一个完整的工作进程。接着给出了一个客户端示例代码,使用了jQuery的ajax方法请求一个Jsonp数据。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
  • Allegro总结:1.防焊层(SolderMask):又称绿油层,PCB非布线层,用于制成丝网印板,将不需要焊接的地方涂上防焊剂.在防焊层上预留的焊盘大小要比实际的焊盘大一些,其差值一般 ... [详细]
  • 基于分布式锁的防止重复请求解决方案
    一、前言关于重复请求,指的是我们服务端接收到很短的时间内的多个相同内容的重复请求。而这样的重复请求如果是幂等的(每次请求的结果都相同,如查 ... [详细]
  • 最近学习了关于使用最为流行的jquery发送请求,在实践中以最为简单的聊天室作为测验的辅助工具,对相关网页开发有一个初步的认识,希望大家能够一起学习进步。首先介绍一下 ... [详细]
author-avatar
捕鱼达人2502873933
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有