架构师面试(三十):IM 分层架构

发布于:2025-04-14 ⋅ 阅读:(22) ⋅ 点赞:(0)

问题

有一段时间没有聊【IM架构】相关的话题了,今天咱们继续聊一波 IM。

IM 系统的水平分层架构一般会包括: 【入口网关层】、【业务逻辑层】、【路由层】 和 【数据访问层】,这里每一层的核心职责是什么呢? 每一层为什么要这样设计呢?

大家可以结合着每一层存在的架构意义具体描述一下。

解析

IM 客户端向服务端发出请求,按请求处理顺序, 水平分层架构的 IM 系统包括【入口网关层】、【业务逻辑层】、【路由层】和【数据访问层】,如下图:

一、【入口网关层】,即 Entry 层

【入口网关层】负责维护与IM终端之间的长连接,不处理任何业务逻辑,与业务相关的请求会直接转发给【业务逻辑层】;简言之,【入口网关层】向客户端提供了 TCP 长连接的接入能力,只有客户端的 “心跳请求” 会被【入口网关层】处理,其他所有请求都由【业务逻辑层】处理。

为什么要这样设计呢?

【入口网关层】与 IM终端是保持着 TCP 长连接,这就要求【入口网关层】不能经常性的重启,所以与业务相关性的代码一定要避免写在这一层;转转 IM 的【入口网关层】的进程已经连续运行好几年了,期间没有任何的重启。

【入口网关层】在代码层面,其本质是两个 Map,即<用户uid,连接fd> 和 <连接fd,用户uid>两个映射关系:我们可以根据 uid找到其对应的 fd连接, 也可以根据连接fd 找到其对应的用户。

二、【业务逻辑层】,即 Logic 层

【业务逻辑层】负责实现 IM 系统所有的业务逻辑,包括用户登录、用户好友、私信消息、系统消息等;这一层的服务是需要频繁升级迭代和经常性重启的,也是我们代码工程师接触最多的。

在工程实践中,为了避免运营活动或边缘功能 对 核心功能造成影响,一般需要对该层进行拆分,比如:转转IM在前期将【业务逻辑层】拆分成了负责核心和轻量级业务逻辑的 Logic服务 与 负责非核心和重量级业务逻辑的 Extlogic 服务。

三、【路由层】,即 Router 层

【路由层】从字面意思理解即可,负责存储在线用户的路由数据。

【入口网关层】是一个服务集群,每一个进程不妨叫做 Entry 进程,每一个 Entry进程会连接大量的客户端,所以【路由层】其本质是一个存储,存储 用户id与Entry之间的映射关系,即:Map<uid, Entry>。

其实描述到这里为止,向用户 push 消息的逻辑链路就基本完整了:首先访问【路由层】,根据用户 uid 获取其所在的 Entry;再访问Entry,根据用户 uid 获取其对应的连接 fd。

四、【数据访问层】,即 Das 层

【数据访问层】负责对存储部分(包括数据库、缓存等)进行增、删、改、查。

很多同学会对这一层有疑惑,为什么要将这一层单独拆出来呢,【数据访问层】的逻辑放在【业务逻辑层】中进行实现不香吗?这样设计是否多此一举呢?

【数据访问层】在架构意义上是为了解耦【业务逻辑层】和【存储层】。

我们知道,【存储层】是整个系统最复杂的部分了,比如:查询压力比较大了,需要增加缓存;单表压力大了,需要分表;存储能力到极限了,需要分库;MySQL 不满足需求了,需要更换MongoDB;加缓存、分库分表、更换存储介质等等,任何一个事情都会让【业务逻辑层】疲于奔命。这个时候,【业务逻辑层】还有精力去继续迭代业务吗?怎么办?在其中间增加一个【数据访问层】,则完美解决这个问题。存储部分的复杂性,由【数据访问层】完全消化,【业务逻辑层】需要的数据只按标注接口从【数据访问层】获取即可。

水平分层架构的 IM 系统,你理解了吗? 

任何疑惑点,我们随时留言探讨!


网站公告

今日签到

点亮在社区的每一天
去签到