在分层架构 IM 系统中,路由层 Router 的核心职责是作为中央存储记录在线用户的连接状态,见下图。
Router 其本质是一个巨大的 Map<uid, EntryIp>,其 key 是表示客户端用户的 uid, 其 value 是客户端连接的 Entry 节点;要判断一个用户是否在线,该用户客户端连接到了哪一个 Entry 节点,Router 是门儿清的。
明确了 Router 的核心职责后,那么Router 需要提供哪些能力呢?
先分析一下,在分层架构 IM 系统中 Entry、Router 和 Logic 三者之间的调用关系,见下图。
- Entry 通过 RPC 调用 Logic,实现业务逻辑的处理;
- Logic 通过 RPC 调用 Entry,实现消息向用户侧的推送;
- Logic 通过 RPC 调用 Router,维护在线用户信息;
- Router 回调 Logic,实现心跳失活用户的及时通知。
所以,Router 需要提供两方面能力:业务接口 和 通知回调。
一、 业务接口
Router 的核心数据结构是一个 Map,其 key 是唯一标识用户的 uid,而其 value 为了方便功能上扩展,可以落地为一个 结构体对象,代码如下:
Map<uid, userInfo>
userInfo {
int userStat;//用户状态 0—离线 1—在线 2—......
long heartbeat;//最近一次心跳时间
int deviceType;//设备类型 0—安卓 1—IOS 2—......
string deviceToken;//用户移动设备token,用于手机推送
string entryAddr; //Entry节点地址, ip:port
}
Router 基于该核心数据结构,向 Logic 提供四个业务接口;这四个业务接口,纯内存操作,而且逻辑简单。
- 用户登录Logic 校验完成用户登录请求后,构建 userInfo 对象,写入到 Router 中。
- 用户登出用户登出时,Logic 直接从 Router 中根据用户 uid 删除记录,或将 userStat 字段置为 0。
- 设置用户信息在多种业务场景下,Logic 会调用该接口:客户端发送心跳请求时,修改 heartbeat 字段值;客户端在线状态下,使用了新的设备进行登录,修改 deviceType 和 deviceToken 字段值,如果连接的是新的 Entry 节点,修改 entryAddr 字段值。
- 查询用户信息Logic 需要向用户主动推送消息时,在 Router 中查询用户是否在线,如果在线,则获取用户客户端连接的 Entry 节点地址。
二、 通知回调
Router 中保存了所有的在线用户;而 Router 不仅仅只是一个内存数据库,它能根据客户端心跳数据判断出失活用户,然后通过回调方式及时通知 Logic 进行处理;Logic 处理的方式是通知相关 Entry 节点及时关闭与客户端之间的连接,释放资源。
我们在前面的文章 IM专题:分层架构IM系统(4)— Entry心跳算法 中分析过,Entry 也会根据客户端心跳数据识别出失活用户,这和 Router 的识别失活用户工作并不冗余,而是相辅相成。
Router 的核心数据结构是一个很大的 Map。通常我们会通过定时扫描的方式,扫描出很长时间未发送心跳包的客户端;在扫描的时候,为了安全,会给这个很大的 Map 加上一把大锁,这会非常影响 Router 的服务性能;如何进行优化呢?见下图
将一个大的 Map 划分成 16 个小 Map,也可以形象地称之为 16 个桶,标记为 0~15;根据公式 uid % 16 可以简单算出用户会落入到哪个桶中。扫描线程按桶进行扫描,扫描到哪个桶,就只对哪个桶进行加锁,如此则大大降低了锁的粒度。根据在线客户端数目,可以对桶的数量进行调整。
最后,总结文中关键:
1、Entry、Logic、Router 三者之间的调用关系为:
a. Entry 接收客户端请求调用 Logic;
b. Logic 向客户端推送消息调用 Entry;
c. Logic 维护在线用户数据调用 Router;
d. Router 扫描出失活用户,回调通知 Logic。
2、Router 向 Logic 提供四个业务接口:
a. 用户登录
b. 用户登出
c. 设置用户信息
d. 查询用户信息
3、Router 通过定时扫描 Map 的方式获取失活用户,为了提升服务性能,将一个大 Map 划分成 多个桶,然后对桶加锁,降低锁的粒度。
作者:棕生 | 来源:公众号——架构之魂
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。