WhatsApp 是全球用户最多的 IM 系统之一,以很小的资源消耗支撑了超大规模的消息通信,通过思考 WhatsApp 的架构选择,可以帮助我们了解怎样打造一个简单高效的消息系统。原文:WhatsApp System Architecture[1]
今天我们要设计一个类似 WhatsApp 的即时通讯服务。
Alexander Shatov@Unsplash
WhatsApp 是全世界大部分人几乎每天都在使用的应用程序,帮助我们以友好便捷的方式联系世界各地的朋友。常用的聊天系统一般分为两种类型,一种永久存储所有的信息,典型的是 Facebook Messenger,另一种只在消息无法直接送达的时候存储信息,一旦消息发送成功并收到确认,就会从系统中删除,典型的是 WhatsApp。
功能性需求
- 支持一对一的聊天
- 支持离线时发送消息
- 支持向包括离线用户在内的其他用户发送消息
- 支持聊天群组
- 支持最多 256 名参与者的 WhatsApp 群组
- 支持视频聊天
- 支持群组视频聊天
- 支持语音消息
- 支持图片、视频、文件分享
- 支持加密消息
- 视频最大 16MB,时长 90 秒到 3 分钟
- 支持已读回执
- 用户最后上线时间(基于不同的场景)
- 已发送、已送达、已阅读状态显式
- 分享文件大小不超过 100MB
- 支持播放 youtube、音频和视频
- 支持视频格式:MP4、3GP、MKV、AVI、MOV
- 一旦文件、视频、音频和图像超过大小限制,将显示状态通知
- 支持分享文件、视频、音频和图像到其他应用程序
- 支持在群组聊天中回复特定的消息
- 允许转发任何消息
- 允许拷贝消息
- 允许保存消息
- 允许将消息存档
- 允许我们私下回复消息
- 允许只发送和查看视频、图像一次,阅后即焚
- 允许删除消息
- 对于特定消息,支持向 WhatsApp 团队报告
- 支持通过 WhatsApp 拍照
- 支持当录音功能设置为全开后进行录音
- 支持访问手机联系人列表
- 支持共享位置(共享实时位置或共享当前位置)
- 支持通过 Facebook Messenger、邮件、微信、Telegram 等分享视频和文件
- 允许编辑、上传、删除用户配置文件
- 允许添加个人简介
- 允许绑定其他设备
- 允许更新状态
- 对于不同的场景,允许定制设置
非功能性需求
- 超低时延
- 永远可用
- 没有延时
- 高可扩展性
- 一致性(在其他设备上显示的内容,将与其他设备同步)
系统架构组件
1. 用户数据库
- 存储用户状态、头像、ID、联系方式等配置文件信息
- 个人头像存储在 AWS S3[2]上,每个头像都有各自的链接
2. 用户服务(API)
- 具有多个端点,可帮助检索有关用户的详细信息,支持获取、检索用户配置信息
3. 映射数据库
- 在我们深入了解之前,需要先了解一下一般通信体系结构的概念。当两个客户端(A 和 B)想要互相通信和发送消息时,必须知道对方的地址(IP、MAC 或任何特定的唯一标识),并通过网络(当前主要是互联网)交换消息,通常客户端会创建双向连接进行通信。这一系统会不断进化,最后可能会像下面的图片一样,其中包括了服务器、客户机、负载均衡器和数据库。
- 我们不使用 HTTP 协议,因为每个用户都需要向服务器发送请求,一旦客户端从服务器接收到响应,HTTP 连接就会关闭,这意味着每个消息都需要等待服务器和客户端之间完成完整的事务。但是,每次都创建 HTTP 连接非常浪费时间和资源,因此我们选择使用 WebSocket 协议,保证连接不会被立即关闭。WebSocket 处理程序 WSH1 将建立用户连接,是一个轻量级服务器,与所有活动用户保持连接。
- 每台机器有大约 65K 个开放端口,即使我们最终使用多达 5K 个端口用于内部使用以及与系统中的其他服务通信,仍然有多达 60K 的端口可以用于与用户连接。一个 WebSocket 处理程序将连接到一个 WebSocket 管理器,该管理器维护了一个哪些 WebSocket 处理程序连接到哪些用户的信息存储库。管理器使用 Redis 作为存储,包含两种类型的信息:哪个用户连接到哪个 WebSocket 处理程序,某个 WebSocket 处理程序上连接的所有用户。当用户和 WebSocket 处理程序的连接中断,可以将他们连接到另一个处理程序,而相关信息也将被更新到 Redis。
- 消息服务:系统中所有消息的存储库。API 通过各种过滤器获取消息,如用户 id、消息 id、发送状态等。新老用户每天都在聊天,因此数据不断增长,当前采用 Cassandra 用于消息服务。WebSocket 处理程序会并行与 WebSocket 管理器、消息服务进行通信。
- 然后我们可以推导出一些场景。例如,发送方连接到服务器,但接收者没有上线,消息存储在数据库中,当接收方连接到服务器时,可以从数据库中获取消息。当发送方未连接到服务器时,消息将保存在设备存储中(可能是 SQLite 或基于平台的任何东西),当发送方联机时,消息将从本地存储中获取并发送到服务器。当两个客户端都连接到服务器时,发送方发送消息,服务器将消息转发给接收方,数据库或设备本地存储中不会保存消息。
- 映射数据库——聊天服务器为发送方(用户 A)创建一个新进程(或线程),如果接收方(用户 B)在线,则同样如此。服务器找到接收方名称,从数据库中取出数据,并找出用户 B 的进程 id(pid),以便将消息发送给用户 B。如果用户 B 想发送消息到用户 A,服务器同样通过映射数据库中用户 A 的名字找到 pid,并将消息发送到该 pid。无论何时当有用户与系统建立连接,都会创建一个新的进程,所有细节都存储在映射数据库中。
在实际应用中,结构应该类似下图:
每个聊天服务器都包含一个队列,队列可以处理过多的消息负载,并且在向不同用户发送任何消息时不会失败。
4. 群组服务
- 对于新创建的群组,也会有一个新的 groupId,这个 groupId 将映射到组中的所有用户。发送消息的时候,聊天服务将找到所有类型的接收方,可能是群组或单个用户,如果是群组,聊天服务将通过群组服务查询到 groupId 相同的所有用户,将消息发送给所有这些用户。
- WebSocket 处理程序不能绑定群组,只能绑定活动用户。因此,当一个发送者想要向一个群组发送消息时,发送者的 WebSocket 处理程序将与消息服务通信,将消息存储在 Cassandra 中。然后消息服务与 Kafka 通信,将这些消息保存在 Kafka 中,并通过一条指令发送给群组。Kafka 会和群组消息处理器交互,发送所有的群组消息,这就是群组服务的机制。群组消息处理程序将与群组服务通信,找出群组列表中的所有用户,然后通过 WebSocket 处理程序将消息单独传递给所有用户。
- 群组服务维护所有与群组相关的信息,比如哪个用户属于哪个组、用户 id、组 id、创建组的时间、添加每个用户的时间、状态、群组图标等。这些数据也将存储在 MySQL 数据库中,该数据库在不同的地理位置有多个从库服务器,以减少延迟。对于访问频繁的群组,将理由缓存优化访问。
5. 最后上线时间服务(Last Seen Service)
- 最后上线时间服务使用最后上线数据库,以便存储最后上线信息。它只保留最后一次上线的时间细节,最新的信息总是替换旧的信息。当用户打开 WhatsApp 并向聊天服务器发送任何与用户相关的请求时,聊天服务器可以调用该服务来更新时间。
6. 消息存储服务器以及临时消息存储数据库
- 当接收方离线时,消息需要加密保存在服务器的数据库中。一旦接收方上线,所有的消息都可以被传递
7. 多媒体消息
聊天服务获取消息并找出消息的类型,一旦聊天服务检测到消息类型是多媒体格式后,就将其存储在 AWS S3 这样的对象存储服务中。这些多媒体文件的存储链接将被存储在 SQL 或 NoSQL 数据库中,并和用户详细信息相映射,可以使用 HTTP 协议来传递这些消息。
- 通过 WhatsApp 发送的图片、文件和视频将在设备端进行压缩和加密,加密后的内容将发送到接收端,内容将在设备端和接收端进行解密。
- 如果一个用户向另一个用户发送图片,该用户将把图片上传到服务器并获得图片 id,然后图片 id 将被发送给另一个用户,另一个用户可以从服务器搜索和下载图片。或者另一种方案是在设备端将图片压缩,并通过负载均衡器发送到资产服务(Asset Service),将图片存储在 AWS S3 中。一旦图片存储到 S3 中,资产服务将返回图片 id,用户可以通过 WebSocket 处理程序将图片 id 发送给另一个用户。
WhatsApp 前端
- Android:Java
- iOS:Swift
- Windows Phone:C#
- Web app:JavaScript/HTML/CSS
- Mac 桌面:Swift/Objective-C
- PC 桌面:C/C#/Java
WhatsApp 后端
- Erlang 是主要的编程语言
- FreeBSD 是操作系统
- Ejabberd 是 XMPP 应用服务器
- BEAM 是 Erlang 虚拟机
- Mnesia 是 Erlang 数据库
- YAWS 是多媒体 web 服务器
系统概要设计
参考资料
- The WhatsApp Architecture Facebook Bought For $19 Billion: http://highscalability.com/blog/2014/2/26/the-whatsapp-architecture-facebook-bought-for-19-billion.html
- WhatsApp System Design: https://www.codekarle.com/system-design/Whatsapp-system-design.html
- Behind the scenes of Chat Applications: https://sudarakayasindu.medium.com/behind-the-scenes-of-chat-applications-38634f584758
- WhatsApp System Design: https://youtu.be/RjQjbJ2UJDg
- Whatsapp System Design or software architecture: https://youtu.be/L7LtmfFYjc4
References:
[1] WhatsApp System Architecture: https://medium.com/interviewnoodle/whatsapp-system-architecture-8df0250d572f
[2] AWS S3: https://aws.amazon.com/s3/