一个.NET开发的即时通讯组件FreeIM,支持点对点通讯、群聊通讯、上线下线消息

大家好,我是宝弟!

今天给大家推荐一个.NET开发的即时通讯组件FreeIM,FreeIM 使用 websocket 协议实现简易、高性能(单机支持5万+连接)、集群即时通讯组件,支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。.

使用场景

好友聊天、群聊天、直播间、实时评论区、游戏。

设计思路

终端(如浏览器/小程序/iOS/android) 统一使用 websocket 连接 ImServer

ImServer(支持集群)根据 clientId 分区管理 websocket 连接;

WebApi 使用 ImHelper 调用方法(如:SendMessage、群聊相关方法),将数据推至 Redis chan;

ImServer 订阅 Redis chan,收到消息后向 终端 推送消息;

  • 缓解了并发推送消息过多的问题;

  • 解决了连接数过多的问题;

  • 解耦了业务和通讯,架构更加清淅;

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

    • WebApi 负责所有业务

举例1、用户A向B发送消息:终端A ajax -> WebApi -> ImServer -> 终端B websocket.onmessage;

举例2、获取历史聊天记录:终端 请求 WebApi(业务方) 接口,返回json(历史消息)。

举例3、A向B发文件的例子:

  • A向 WebApi 传文件

  • WebApi 通知 ImServer,ImHelper.SendMessage(B, "A正在给传送文件...")

  • B收到消息,A正在给传送文件...

  • WebApi 文件接收完成时通知 ImServer,ImHelper.SendMessage(B, "A文件传输完毕(含文件链接)")

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

FreeIM 强依赖 redis-server 组件功能:

  • 集成了 redis 轻量级的订阅发布功能,实现消息缓冲发送,后期可更换为其他技术

  • 使用了 redis 存储一些关系数据,如在线 clientId、频道信息、授权信息等

系统配置
 

ImServer 服务端

ImServer 服务端支持 .NET6.0、.NETCore2.1+、NETStandard2.0

安装依赖:

dotnet add package FreeIM

配置:

public void Configure(IApplicationBuilder app){    app.UseFreeImServer(new ImServerOptions    {        Redis = new FreeRedis.RedisClient("127.0.0.1:6379,poolsize=5"),        Servers = new[] { "127.0.0.1:6001" }, //集群配置        Server = "127.0.0.1:6001"    });}
 

WebApi 业务端

public void Configure(IApplicationBuilder app){    //...
    ImHelper.Initialization(new ImClientOptions    {        Redis = new FreeRedis.RedisClient("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 支持 .NetFramework 4.5+、.NetStandard 2.0

ImHelper方法 参数 描述
PrevConnectServer (clientId, string) 在终端准备连接 websocket 前调用
SendMessage (发送者, 接收者, 消息内容, 是否回执) 发送消息
GetClientListByOnline - 返回所有在线clientId
HasOnline clientId 判断客户端是否在线
EventBus (上线委托, 离线委托) socket上线与下线事件
频道 参数 描述
JoinChan (clientId, 频道名) 加入
LeaveChan (clientId, 频道名) 离开
GetChanClientList (频道名) 获取频道所有clientId
GetChanList - 获取所有频道和在线人数
GetChanListByClientId (clientId) 获取用户参与的所有频道
GetChanOnline (频道名) 获取频道的在线人数
SendChanMessage (clientId, 频道名, 消息内容) 发送消息,所有在线的用户将收到消息
  • clientId 应该与用户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) {        //...    };})
集群分区

单个 ImServer 实例支持多少个客户端连接,3万?如果在线用户有10万人,怎么办???

部署 4 个 ImServer:

  • ImServer1 订阅 redisChan1

  • ImServer2 订阅 redisChan2

  • ImServer3 订阅 redisChan3

  • ImServer4 订阅 redisChan4
     

WebApi(业务方) 根据接收方的 clientId 后四位 16 进制与节点总数取模,定位到对应的 redisChan,进行 redis->publish 操作将消息定位到相应的 ImServer。

每个 ImServer 管理着对应的终端连接,当接收到 redis 订阅消息后,向对应的终端连接推送数据。

 资源获取方式 

https://github.com/2881099/FreeIM