IM最基本的功能就是即时消息交换,那么一个送出的消息将经历哪些过程才能最终送达目的地?
下面给出一个过程描述:
1. 消息从客户端发出经过网络由客户端所直接连接的服务器接收
2. 接入服务器接收到网络字节流后重组消息包(协议解包的过程)
3. 合法性判断
- - 只有已登陆的用户才能发送消息
- - 消息包的长度限制
4. 协议分析(得到消息的类型、格式、目的地等)然后交给合适的程序模块进行处理
5. 目的地定位(判定目标用户的接入服务器)
- - 无法定位(不在线)
- - 定位到唯一位置(单一登陆)
- - 定位到多个位置(多点登陆)
6. 消息路由
- - 无法定位时:根据消息类型判定丢弃或离线存储
- - 定位唯一时:直接进行消息投递
- - 定位不唯一时:按路由策略进行投递,其中策略可能有全部发送给多个位置、按定位优先级选择最高级发送、按最后活跃或登陆位置投递等。
以上过程在不同规模的IM服务实现中差异却很大。
例如,在几十万用户规模内可能全部流程都在一个程序中完成,部署单台服务器即可支撑,定位非常简单因为不跨越服务器,用户的在线、离线等各种状态也可以直接保存在服务器内存中非常高效,但一旦超出了单一服务器的支撑规模,引入集群化则带了很多复杂性。
集群化后最大的不同在于用户信息(状态、接入位置)的外移,原本存储于服务器内存中的信息将转移到公共分布式集群缓存中,对内存和分布式缓存的访问开销本身的差距就在不同的数量级上,而且分布式缓存还可能存在用户信息更新的延迟、脏数据等问题,因此消息交换的处理机制必须结合这些集群特征进行考虑。
以下是实现时的几个注意点:
1. 连接到同一接入服务器上、连接到同一集群的不同服务器上和连接到不同集群服务器上的用户之间的消息交换流程实现是不同的。
2. 用户登陆信息(状态、接入位置)外移分布式缓存后,如果在多个集群间(不同集群可能处在不同IDC机房中)存在同步状态信息,则不可依赖状态信息对用户的可送达性进行预先判断,因为状态可能存在明显的滞后,这类情况主要是针对跨集群消息交换实现时。
3. 分布式缓存中可能保存了大量用户的实时信息,但可能存在用户下线时不能及时清除这些与本次登陆有关的缓存数据(例如:接入服务器故障导致的清理工作失败),缓存存在垃圾数据膨胀的可能,需设计有效的后台清理机制来维持缓存的可用性。