世界上规模最大的IM系统,是微信的2倍,是如何实现?

世界上规模最大的IM系统,是微信的2倍,是如何实现?地球上有两个社交的App,一个是中国使用的微信,一个是其他国家使用的WhatsApp。开发商: Meta Platforms, Will Cat

大家好,欢迎来到IT知识分享网。

世界上规模最大的IM系统,是微信的2倍,是如何实现?

地球上有两个社交的App,一个是中国使用的微信,一个是其他国家使用的WhatsApp。根据Facebook CEO 马克·扎克伯格的说法,(2020年)每天有超过1000亿条信息通过WhatsApp发送,日活用户20亿;相比之下,微信日活是10.9亿,每天发送450亿条。Whatsapp相当于2个微信。 有了如此近乎天文数字的流量,人们不禁想知道WhatsApp是如何工作?它的系统设计、服务器架构、技术。它是如何处理这么多并发用户和消息的?什么样的框架和编程语言能够实现这种规模?他们如何保护所有数据的安全? 等等。 在本文中,我们将深入探讨WhatsApp的架构和系统设计。我们将回答上述所有问题以及更多问题。

产品需求概述

基本信息

原作者: Brian Acton, Jan Koum

开发商: Meta Platforms(改名元宇宙平台的脸书), Will Cathcart (WhatsApp总裁)

第一个版本发布时间: 12年前的2009年1月

当前稳定版本:

  • iOS 2.21.170版 2021年8月30日
  • Android 2.21.16.20版, 2021年8月18日
  • Windows 2.2132.6版, 2021年8月24日
  • macOS 2.2132.6版, 2021年8月23日

开发语言: Erlang

支持的操作系统: Android, iOS, KaiOS (即Mac OS), Windows等客户端必须连接到移动端才可以。

文件大小: iOS 178兆; Android 33.85兆

语言支持: iOS 支持40种语言; Android支持60种语言

版权: 私有软件,支持EULA

网站地址: WhatsApp.com

产品数据

月活增长情况

世界上规模最大的IM系统,是微信的2倍,是如何实现?

2014年4月22日,WhatsApp拥有5亿月活跃用户,7亿照片和1亿视频每天被分享,消息系统每天处理超过100亿条消息。

2014年8月24日,Koum在他的推特账户上宣布,WhatsApp在全球拥有超过6亿活跃用户,每月增加约2500万新用户,即每天833,000名活跃用户。

2017年5月,据报道,WhatsApp用户每天在该应用上花费超过3.4亿分钟进行视频通话。这相当于每天大约646年的视频通话。

2017年2月,WhatsApp在全球拥有超过12亿用户,到2017年底达到15亿月活跃用户。

2020年1月,WhatsApp在谷歌应用商店注册了50亿安装,成为Facebook之后的第二个实现这一里程碑的非谷歌应用。

功能需求

  • 支持一对一聊天
  • 支持群聊,每个群上限256人
  • 支持离线消息发送和接收
  • 支持图像、视频和文件共享功能 视频控制在16MB以内/90秒长度
  • 文件控制在100MB以内,超过则会提醒
  • 支持在线播放Youtube、语音和视频
  • 支持多种音视频格式MP4, 3GP, MKV, AVI,and MOV
  • 支持分享各种类型文件到其他应用
  • 支持拍照
  • 显示已读/收到的消息 发送、接收、已读的收据
  • 聊天方式,支持文字、视频 支持发送文字、声音、图片、文件
  • 显示和用户的最后聊天的时间
  • 支持针对特定消息的恢复
  • 支持转发、复制、保存、归档消息
  • 支持针对特定消息的私聊
  • 支持删除消息
  • 在视频通话时支持录音
  • 支持消息加密
  • 支持访问通讯录
  • 支持位置共享
  • 支持修改、上传、删除个人信息 添加个人传记
  • 连接到其他设备
  • 更新个人状态
  • 个性化设置

非功能需求

  • 低延迟
  • 高可用
  • 不应该有任何滞后
  • 高可扩展的

技术栈

前端

WhatsApp支持几乎所有平台。它有一个iOS应用程序、安卓应用程序、桌面应用程序、网络应用程序和视窗手机应用程序。直到2017年,你甚至可以在黑莓上使用WhatsApp。

有这么多受支持的平台,你可能已经猜到WhatsApp将是一个混合应用。但是,事实上,不是。他们实际上为每个平台构建了一个本地应用。以下是用于构建每个平台的所有支持平台的前端语言列表:

  • iOS: Swift
  • Windows Phone: C#
  • Web app: JavaScript/HTML/CSS/
  • Mac桌面应用:Swift/Object-C
  • PC桌面应用:C/C#/Java

除了编程语言本身,WhatsApp在前端使用的另一个重要技术是SQLite数据库。SQLite是一个独立的、独立的关系数据库,旨在嵌入到应用程序中——这意味着它存在于您的设备上。WhatsApp用它来存储对话。由于每次打开应用程序时从云中下载所有消息都是浪费资源,WhatsApp选择将消息存储在本地。事实上,WhatsApp只存储消息,直到收到消息时才删除。

后端

据我们所知,目前的WhatsApp后端系统设计如下:

  • 主要的编程语言:Erlang
  • 操作系统:FreeBSD
  • XMPP应用服务器:Ejabberd
  • 基于Erlang的虚拟机:BEAM
  • 基于Erlang的数据库:Mnesia
  • 多媒体网络服务器:YAWS

Erlang

WhatsApp选择erlang来支持如此大规模的并发。

Erlang是一种面向构建并发、可扩展和可靠系统的函数式编程语言。它使用基于进程的“参与者模型”,每个独立的小进程通过消息相互通信。这些进程可以创建新进程、发送消息、接收消息并修改其状态。

它基于进程的特性使Erlang具有极高的并发性、可伸缩性和可靠性。

这些进程还可以与运行它的核心之外的进程通信。这使得水平(通过添加更多机器)或垂直(通过添加更多内核)缩放系统变得容易。最后,由于这些过程可以相互通信,更重要的是,可以相互重启,因此很容易构建自愈系统。如果一个错误使一个进程崩溃,另一个进程可以重新启动它。

FreeBSD

WhatsApp创始人的一个有趣的技术选择是选择FreeBSD作为操作系统,而不是更广泛使用的系统(如Linux)。

WhatsApp的联合创始人之一布莱恩·阿克顿在接受《连线》采访时谈到了这一决定:

“Linux是复杂的野兽。FreeBSD的优势在于它是一个具有非常好的端口集合的单一发行版。”

此外,当涉及到原始性能时,尤其是在每个数据包的系统负载方面,没有其他操作系统能打败FreeBSD。

然而,归根结底,他们决定使用FreeBSD的真正原因可能是因为两位联合创始人在雅虎有很长的使用经验!

Ejabberd

Ejabberd是一个用Erlang编写的开源XMPP服务器。WhatsApp使用XMPP的修改版本作为处理消息传递的协议。即使是WhatsApp使用的Ejabberd服务器也是高度定制的,以优化服务器性能。

Ejabberd处理应用程序的消息路由、可交付性和即时消息通用侧面。Ejabberd的特点包括:

  • 一对一的消息传递
  • 群聊
  • 存储和转发离线消息
  • 联系人列表和在线状态

Mnesia

为了存储数据和临时消息,WhatsApp使用了一个名为Mnesia的基于Erlang的分布式数据库管理系统。这个数据库管理系统提供了许多传统数据库所没有的优点,例如:

  • 实时键/值查找
  • 高容错性
  • 动态配置
  • 复杂对象

Mnesia也是唯一一个用Erlang编写的数据库管理系统。这本身就是一个好处,因为应用程序中的Erlang和DBMS中的Erlang之间没有数据结构差异。因此,编码更快、更明确。

BEAM

BEAM,即Bogdan’s Erlang Abstract Machine,是编译和执行Erlang源代码的虚拟机。BEAM是专门为高并发应用程序设计的——非常适合WhatsApp的用例。BEAM的秘诀是不共享内存的轻量级进程,由调度器管理。这些调度器可以跨多个内核管理数百万个进程。这使得BEAM具有高度的可伸缩性,并且能够抵抗故障,例如由高流量负载、系统更新和网络中断引起的故障。

BEAM对WhatsApp系统设计至关重要,WhatsApp团队已经发布了许多核心源代码的补丁和修复。

YAWS

YAWS(Yet Another Web Server)是一个基于Erlang的网络服务器,非常适合动态内容。WhatsApp使用YAWS存储多媒体数据。YAWS本身使用HTML5 WebSockets,通过在服务器和应用程序之间建立可靠而快速的连接来简化双向通信。通过使用这项技术,WhatsApp能够在数十亿台设备上近乎实时地发送和接收多媒体数据。

通讯机制

WhatsApp在Ejabberd服务器上使用高度修改的XMPP版本(稍后会有更多介绍)与客户端通信。

客户端上的XMPP打开一个SSL套接字到WhatsApp服务器。所有发送的消息都在服务器上排队,直到客户端打开或重新连接到此套接字以检索消息。一旦客户端成功检索到消息,成功状态就会发送回WhatsApp服务器。然后,服务器将此状态转发给原始发件人;通过在成功发送的消息旁边添加“复选标记”图标,让他们知道消息已经收到。

系统架构

软件架构

世界上规模最大的IM系统,是微信的2倍,是如何实现?

软件架构

部署架构

2014年WhatsApp用户数为5亿, 需要大约550台服务器和超过11,000个运行Erlang的内核。2017年,在被Facbook收购四年后,WhatsApp被从IBMSoftLayer的云中移除,转到facebook的私有云上。2020年用户数超过20亿的用户。

世界上规模最大的IM系统,是微信的2倍,是如何实现?

部署架构

从左侧开始,我们有多个不同的客户端(移动和网络应用),每个客户端都托管一个用于存储对话的本地SQLite数据库。

客户端使用HTTP WebSocket从YAWS Web服务器发送和检索图像和视频等多媒体数据。XMPP是用来向其他用户发送这些文件和其他消息的。

发送XMPP消息时,将执行上面描述的一系列步骤。首先,它被发送到WhatsApp在BEAM和FreeBSD上运行的自定义Ejabberd服务器。Ejabberd服务器将消息保存在Mnesia数据库表中,并将其放入队列。当接收用户打开应用程序,从而重新连接到套接字时,队列中的消息将通过Ejabberd服务器路由并传递给接收方。一旦确认成功传递,消息将从Mnesia数据库中删除。

核心用例实现

当两个用户都在线时

假设用户U1想要向用户U2发送消息。现在我们可以从流程图中看到,U1连接到WSH1(Web Socket Handler)。Web Socket Handler 是一种轻量级服务,即采用长链接来对接到活跃的用户。考虑到WhatsApp和FacebookMessenger每天处理的规模,系统中会有大量的WebSocket Handler 服务。

评估Web Socket Handler所需要的服务器数量。每台机器支持有大约65K开放端口。预留5K端口用于内部使用以及与系统中的其他服务通信,剩余60K端口可用于Web Socket Handler服务,也就是一台机器可以服务于6万用户, 20亿用户需要3万多台机器。此外这些机器还需要分布到世界各地,就近部署来减少延迟。

Web Socket Handler 将连接到Web Socket Manager,这个Manager记录Web Socket Handler 和所连接的用户的映射信息, 后端采用Redis数据库,记录如下信息:

  • 哪个用户连接到哪个Web Socket Handler
  • 所有用户连接到Web Socket Handler的内容

当用户断开和Web Socket Handler之间的连接并重新连接到另一个Handler时,Manager会将这个信息更新到Redis中。

Web Socket Handler在调用Web Socket Manager 的同时还调用消息服务。消息服务是系统中所有消息的存储库。它提供开放接口, 支持通过各种过滤器获取消息,如用户标识、消息标识、传递状态等。这个消息服务采用Cassandra作为数据库。可以预期的是,新用户将每天不断添加到系统中,新老用户将每天不断进行新对话,即消息服务需要建立在能够处理持续增加的数据的数据存储之上。由于它向WebSocket Handler开放的API数量有限,可以执行的查询参数也是有限的。Cassandra是最适合这些需求和查询模式的数据库。在选择最佳存储解决方案的一文中介绍Cassandra和Redis的比较。

IM系统对消息存储有两种方式:

  1. 以脸书Messenger为代表,永久存储所有信息;
  2. 以微信、WhatsApp为代表,只存储信息,直到它们无法传递。一旦我们收到消息被成功接收的确认,它们就可以从系统中删除。

存储方式会影响数据库的选择。Cassandra中删除操作处理效率不高,对WhatsApp来说并非是一个好的选择。

现在让我们回到U1和U2正在进行的对话。正如我们从架构流程图中看到的,U1连接到Web Socket Handler,即WSH1。因此,当U1决定向U2发送消息时,它将此消息传达给WSH1。然后,WSH1将调用Web Socket Manager,获取正在处理U2 的 Web Socket Handler 即 WSH2。同时WSH1调用消息服务,该服务将消息保存到Cassandra中,并为其分配消息id,例如M1。现在WSH1有一个消息id M1,并且知道U2连接到WSH2,它将与WSH2对话。

用户只要在线, 都会被连接到Web Socket Handler。这时候有两种情况:

  1. U2可能正在和U1聊天,在这种情况下,M1将立即被传递给U2, U2可以看到这个消息;
  2. U2在线, 可能和别人而不是U1聊天,在这种情况下,消息只会被传递到U2即可。

相应地,WSH2将通知消息服务U2已经看到或者收到这个消息了。还有一种可能是我们不想存储消息的已读/已收状态,但这个状态还得保存一段时间。考虑这种情况: U1向U2发送消息,然后U1就离线了。现在U2已经收到消息M1,但是U1不知道。因此,只要消息还没有传达给U1,状态都将存储在Cassandra中。一旦U1收到“消息的状态”(不是消息),如果需要,它可以被删除。

在向U1传达“U2已经收到或看到消息”的同时,WSH2将再次通过Web Socket Manager找到连接到U1的WSH1,然后与WSH1交互。如果U1和U2有一个包含多个消息的完整对话,则Web Socket Manager将会收到大量的调用。为了避免这种情况,每个Handler将缓存2种类型的信息:

  • 哪些用户连接到自己,因此如果U1和U2都连接到同一个Handler,则可以避免对WebSocket Manager的调用。
  • 最近会话的相关信息,例如哪个用户连接到哪个Handler。

还有一个很重要的问题,就是缓存时间的设置。Web socket需要把最近对话的信息缓存多久?这个缓存时间会非常低。正如我们前面提到的,Web Socket Handler将分布在全球各地,以减少延迟。但这也意味着,可能由于连接问题、网络链路或其他此类原因,用户和Web Socket Handler之间的连接可能会中断,用户将与另一个Handler连接,即关于其他Web Socket Handler的信息将变得过时了。我们不想让有限的缓存空间充满过时的信息,因此缓存时间设置得很短。

当接收者离线时

我们已经看到了两个用户都在线时的流程。当U1试图向离线的U3发送消息时会发生什么?WSH1调用WebSocket Manager以找出哪个Handler连接到U3,发现U3没有连接到任何Handler,因此这部分流程到此结束。与此同时,它还调用消息服务,在该服务中,消息存储时被分配一个id,例如M2。现在,当U3上线时,假设它连接到WSH3,WSH3做的第一件事是检查消息服务是否有任何未交付的U3消息,这些消息将通过WSH3发送到U3。然后WSH3将以前面讨论的方式向WSH1传达状态的这一变化。

竞争条件(Race Condition)

是的。这里可能存在竞争条件。WebSocket Handler对WebSocket Manager和消息服务的调用是并行的。此外,请注意,在与服务通信时,系统已进行更改,预计会有轻微延迟。当WSH1调用Web Socket Manager来核实U3状态时,恰巧U3上线了,这里会发生一些事情-

  • WebSocket Manager 返回U3未连接到任何WebSocket Handler
  • WSH3调用消息服务,获取U3的所有未交付消息。
  • WebSocket Manager存储时,WSH3正在处理U3
  • M2储存在Cassandra里

现在WSH1认为U3不在线,将消息存储在消息服务中,并认为它的工作已经完成。WSH3认为它已经为U3获取了所有未传递的消息。但实际上,M2还没有交付。有一些方法可以处理这种竞争条件,其中一个更流行的方法是轮询。WebSocket Handler将每隔几分钟轮询一次消息服务,以确保他们没有错过任何消息。

本地缓存

假设当U1向U3发送消息时,U1处于脱机状态,即没有连接到任何Web Socket Handler。在这种情况下,消息将被存储在设备上的本地数据库中。一旦设备连接到网络和WebSocket Handler,它将从本地数据库中提取所有消息并发送它们。

群聊

到目前为止,我们讨论的是WhatsApp上1:1的聊天,即单聊是如何实现的。 群聊实现有所不同。 假设U1想向G1发送一条消息。现在,组的行为会与用户有点不同。Web Socket Handler无法跟踪到组,它只跟踪活动用户。因此,当U1想要向G1发送消息时,WSH1调用消息服务,U1想要向G1发送消息,消息M3存储在Cassandra中。消息服务现在将与Kafka通信。M3被保存在Kafka中,指令它必须被发送到G1。现在Kafka将与 Group Message Handler进行交互。 Group Message Handler.监听Kafka并发出所有组消息。有一种叫做Group Service 的东西可以跟踪所有群组中的所有成员。 Group Message HandlerGroup Service 对话,找出G1中的所有用户,并遵循与Web Socket Handler相同的过程,将消息逐个传递给所有用户。

传递资料

文本消息并不是WhatsApp上分享的唯一内容。当人们通过WhatsApp发送图像、文件和视频时,将在设备端被压缩和加密,加密的内容将被发送到接收者。即使在接收的同时,内容也会在设备端以加密的格式被接收并解密。在本文中,让我们只考虑压缩步骤。

假设U3正在向U2发送图像。这将分两步进行。

  • U3将上传图像到服务器并获取图像id
  • 将图像ID发送到U2并且U2可以从服务器搜索和下载图像。

如前所述,Web Socket Handler是一个轻量级服务器,即Web Socket Handler上没有繁重的逻辑。图像将在设备端压缩,并通过负载均衡器发送到Asset Service(资产服务),资产服务将内容存储在S3上。S3接收的图像或者其他的内容按需要设置是否加载到CDN上。 一旦图像被加载到S3,资产服务将发送图像id(例如I1)到U3,U3将通过所讨论的Web Socket Handler将其传递给U2。

这里我们可以进行一些优化。例如,在一个引人注目的政治或体育事件中,很多人最终可能会分享同一个图像,我们可能会得到同一个图像的多个副本。为了避免这种情况,在将图像上传到资产服务之前,U3将发送图像的哈希值,如果哈希值已经存在于资产服务中,则不会再次上载内容,但会将针对相同图像/内容的id发送到U2。我知道,你一定在想多重碰撞?为了解决这个问题,我们将发送通过多种算法计算的多个哈希,而不是只发送1个哈希。如果所有哈希值都匹配,则很有可能是相同的图像,不必再次上传。

现在我们已经讨论了您在流程图中可以看到的几乎所有内容。但是这个User Service用户服务是什么呢?而Group Service群服务到底是做什么的呢?

用户服务存储用户相关信息,如姓名、id、个人资料图片、偏好等,通常存储在MySQL数据库中。此信息也缓存在Redis中。

组服务维护所有组相关信息,如哪个用户属于哪个组、用户标识、组标识、创建组的时间、每个用户入群的时间、状态、组图标等。这些数据也将存储在MySQL数据库中,该数据库将在不同的地理位置有多个从服务器,以减少延迟。当然,这些数据将被缓存在Redis中。通常,用户服务和组服务将首先连接到Redis来查找数据,只有在Redis中找不到数据的情况下才会查询MySQL DB。

数据分析

用户执行的每个动作都可以用于某种分析,比如如果一个人谈论了很多关于运动的事情,他们可能就是运动爱好者。这些事件要么被Analytics Service分析服务发送到Kafka,要么被当作消息直接发送到Kafka。如果是发送图像的事件,分析服务将处理图像并附加一些标签,如“体育”、“足球”、“梅西”等,并将这些信息发送给Kafka。Kafka可以进一步连接到Spark流处理服务,该服务可以在内容流入时进行分析,也可以将其转储到可以运行各种查询的Hadoop集群中。

最后上线时间(Last Seen)

已阅服务会侦听各种事件,从中计算用户最后看到某条消息的时间。 已阅时间保存在Redis或者Cassandra中。Redis不适合存储大颗粒的数据,如果有一些额外的信息需要和已阅时间存在一起, Cassandra会更合适。

Whatsapp中的事件分为两种,由应用程序触发的事件和由用户触发的事件。

  • 应用程序事件–例如当Web Socket连接被创建时,等等。这些事件不会被已阅服务跟踪。
  • 用户事件——比如用户在应用中打开或关闭或执行其他操作时。这些事件将用于跟踪最后一次看到的时间。

水平伸缩

到目前为止,我们讨论的所有组件都是水平可伸缩的。我们可以根据需要增加或删除实例。监控和其他一些需要满足我们“无滞后”要求的东西。我们将监控所有服务的CPU利用率、网络服务的延迟、Kafka和数据库的磁盘利用率等,当我们看到性能下降或任何延迟时,我们会添加更多节点。基于这种监控和警报,我们可以编写脚本来自动执行一些操作,例如如果磁盘实用程序达到80%,则可以启动另一个数据库实例,其CPU利用率达到85%,添加另一个Web Socket Handler 服务的实例,等等。

安全机制

消息传输安全

WhatsApp使用端到端加密。理想情况下,这意味着只有消息的原始发送者和真正的接收者才能阅读纯文本消息。

当您发送消息时,它会使用特定的加密协议进行加密(接下来会有更多内容)。WhatsApp然后将此加密消息存储在他们的服务器上,直到将其传递给收件人。发送时,收件人的设备使用唯一的密码密钥将消息解密回可读的明文消息。在整个过程中,WhatsApp永远不知道你信息的内容。

WhatsApp的加密技术被称为Signal Encryption Protocol,,由Open System Whispers公司开发,是异步消息系统的现代、开源、强加密协议。2016年4月5日,WhatsApp和Open Whisper Systems宣布,他们已经完成了对WhatsApp上“各种形式的通信”的端到端加密,用户现在可以相互验证密钥。用户还可以选择启用首次使用信任机制,以便在通信人的密钥更改时得到通知。根据与公告一起发布的白皮书,WhatsApp消息是用信号协议加密的。WhatsApp调用使用SRTP加密,所有客户端-服务器通信都在单独的加密通道内分层。WhatsApp使用的信号协议库是开源的,并根据GPLv3许可发布。端到端加密可能会让你在理论上感到安全。在实践中,端到端加密并不像人们希望的那样保护隐私。

数据备份安全

2021年10月14日,Whatsapp为iOS和安卓用户推出端到端的数据加密备份机制。在安卓和iOS上,备份数据被存储在iCloud或者谷歌Drive上, 这意味着苹果公司或者谷歌可以按照政策要求将数据提交给政府。为此, WhatsApp允许用户为备份数据设置密码或者64位的加密密钥,理论上来说是无法激活成功教程的。

如上是从现有资料中分析的WhatsApp的架构, 对本文有兴趣的同学,可以评论下留言,欢迎交流。

参考资料

CodeKarle: WhatsApp系统设计|Slack/FBMessenger系统设计

Understanding WhatsApp’s Architecture & System Design

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/79083.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信