由于多年前开发了一款聊天软件,今天朋友给我打电话,说他们公司准备开发一款内部使用的沟通交流工具,找我咨询关于即时聊天软件一些经验,于是跟他聊了一些关于这方面的东西,所以在这里做个总结。
最简单的聊天系统
设计一个聊天系统首先想到的设计就是:
A发消息给B,B发消息给A,A,B能相互收到对方发送的消息。我们不考虑在同一个局域网或者UDP穿透等特殊情况的,A,B是网络上随意的两台设备,所以我们需要通过一台A,B能同时访问到的机器做中转,A发消息给B的过程是:A, B同时连接Core服务器, A把消息发送给Core服务器,Core服务器把消息转发给B,B发消息给A的过程是同理,一个简单的聊天系统就成型了。
可以用的方案
最简单的聊天系统成型,但是这仅仅是最简单的系统,仅仅是一对一聊天,谈不上可以用性,真正可用的系统我们必须解决如下问题:
为了解决上面的问题,提出了一套新的架构方案,如图:
图中节点A,B,C,D为客户端,为了图形容易观看,仅A画出了跟服务器的连接线连接了服务器,其他客户端连接也跟A相同。
架构图中一共有6个服务器和两个存储:http用户服务器,gate服务器,core服务器,http离线消息服务器,http文件服务器,push服务器和数据库存储,文件系统存储。现在来分析这些服务器和存储的作用:
1, http用户服务器主要负责三个方面:(1)负责客户端的注册,把注册的用户信息写入数据库, (2)用户登陆时验证用户信息的正确性,并返回用户的个人信息, (3)添加和删除好友时把信息写入数据库。所以此服务器跟数据库之间有数据的写入刷新,也有读取,所以是双向箭头。
2,core服务器主要是消息的判别和转发,core收到消息,判别消息是否正确(从数据库中查看消息来源用户和目标用户是否为好友,是否为正确格式的消息,登陆信息是否过期等),返回重新打包成发送给客户端接收的消息给gate服务器,让gate服务器发送给客户端。此过程中core服务器还可以做其他操作,例如存储消息。
3,gate服务器负责客户端信息的收发工作,作为core服务器和客户端之间的桥梁,减少客户端直接连接core服务器产生的连接管理工作,gate来直接管理客户端的连接,core只需要负责消息的判别和转发。如果gate对客户端的消息发送失败,把消息作为离线消息保存到数据库,如果是移动端要把消息通知给push服务器。
4, push服务器专门接收gate服务器检测到的移动端不在线的情况下发送过来消息并把消息推送给客户端。
5,http离线消息服务器主要功能是获取客户端没有登陆或者移动客户端App在后台与gate服务器连接中断时未即时收到的消息。
6, http文件服务器主要作用是发送文件语音和视频文件时用来做文件中转服务。
现在整理如何通过上述服务器来实现一个正确的聊天流程:
首先我们把消息分为两类,第一类是普通的文本消息,第二类是语音视频和文件消息。
普通文本消息的发送和接收流程,客户端用http用户服务器注册成为用户,通过http用户服务器登陆并获取用户信息,此时用户是登陆状态,连接gate服务器,并发送消息给好友,gate服务器把消息转发给core服务器,core服务器处理消息后把消息转发给gate服务器,gate服务器发送消息给目标机器,发送成功,消息就发送完成了。如果gate服务器消息发送失败,gate服务器需要把消息作为离线消息保存到数据库,gate服务器再判断目标机器是移动设备,如果目标是移动设备,gate服务器则把消息传递给push服务器,push服务器负责推送消息给目标客户端。目标客户端连接http离线消息服务器获取离线消息。
接下来看语音视频和文件消息的流程,具体工作方式以客户端A发送文件给客户端B为例,A首先把文件通过HTTP方式上传到http服务器,文件上传完成后http服务器保存图片到文件系统,并把文件的全局路径返回给上传的客户端A,客户端A把返回回来的路径作为文本消息再发送给目标客户端B,目标客户端B收到文本消息后解析出文件的全局路径然后下载,这时整个文件传送过程完成。
由上所述,这个架构满足了提出来关于聊天系统需要满足的要求,并解决的了所有提出的问题,所以这是一个可用的聊天系统架构。如果一个小范围内部使用的系统,用户量和消息量都不大的情况下,可以按照这个架构去实现一个即时聊天(IM)系统。其实微信这种量级的系统抽象出来,结构上也差不了太多,只是中间采用了很多分布式系统来提高处理速度和稳定性,下一步我们来做分布式架构的即时聊天(IM)系统。