微信、WhatsApp和其他即时通讯应用程序背后的技术是什么?

78

我渴望了解不同实时通讯应用的架构。它们是否使用任何通用的协议/架构?


我了解过以下内容:可扩展消息和状态协议(XMPP);ErLang;参考资料:http://www.erlang-factory.com/upload/presentations/558/efsf2012-whatsapp-scaling.pdf - Ademir José
3个回答

93
《Facebook以190亿美元收购的WhatsApp架构》解释了WhatsApp设计中涉及到的架构。
以下是链接中的通俗易懂的概括:
  • WhatsApp服务器几乎完全采用Erlang实现。

  • 后端消息路由的服务器系统使用Erlang实现。

  • 令人瞩目的成就是,通过一个真正小的服务器占用来管理活跃用户数量。团队共识是这主要得益于 Erlang。

  • 有趣的是,Facebook聊天室在2009年也是用Erlang编写的,但他们放弃了,因为很难找到合格的程序员。

  • WhatsApp服务器起初基于ejabberd开发。

  • ejabberd是一个著名的用Erlang编写的开源Jabber服务器。

  • 最初选择它是因为它是开源的,得到开发者非常好的评价,容易上手,并承诺Erlang长期适用于大型通信系统。

  • 接下来的几年时间花费在重写和修改ejabberd的一些部分上,包括从XMPP转向内部开发的协议,重构代码库和重新设计一些核心组件,并对Erlang虚拟机进行了许多重要的修改以优化服务器性能。

  • 为了处理每天500亿条消息,重点是打造一个可靠的系统。盈利是稍后考虑的问题,还有很长的路要走。

  • 系统健康状态的主要指标是消息队列长度。所有节点上进程的消息队列长度都在不断监控中,如果它们积累超过预设阈值的积压,则会发送警报。如果一个或多个进程落后,就会发出警报,这将提供下一个瓶颈位置的指针。

  • 多媒体消息是通过上传要发送的图像、音频或视频到HTTP服务器,然后发送内容链接以及它的Base64编码缩略图(如果适用)来发送的。

  • 通常每天会推送一些代码,经常是多次,但一般会避开高峰期。 Erlang可帮助在将修复程序和功能推向生产时更加积极。热加载意味着可以在不重新启动或流量转移的情况下进行更新。错误通常可以非常快速地撤消,也可以通过热加载实现。系统倾向于解耦合得更多,这使得逐步推出更改非常容易。

  • WhatsApp应用程序使用什么协议?SSL套接字连接到WhatsApp服务器池。所有消息都在服务器上排队,直到客户端重新连接以检索消息。成功检索消息后,将该状态发送回WhatsApp服务器,后者将此状态转发回原始发送方(将其视为消息旁边的“检查标记”图标)。一旦客户端接受了消息,消息就会从服务器内存中消失

  • WhatsApp内部的注册流程是如何工作的?WhatsApp过去是基于手机IMEI号创建用户名/密码。这最近已更改。 WhatsApp现在使用从应用程序发送唯一的5位数PIN的一般请求。 WhatsApp随后将向指定的电话号码发送短信(这意味着WhatsApp客户端不再需要在同一手机上运行)。根据PIN码,应用程序然后向WhatsApp请求一个唯一的密钥。此密钥被用作所有未来调用的“密码”(此“永久”密钥存储在设备上)。这也意味着注册新设备将使旧设备上的密钥无效。


  • ejabberd是基于XMPP的。那MQTT呢?我听说Facebook Messenger正在使用它。 - Manish Kumar

    34
    WhatsApp选择Erlang作为一种语言来编写可扩展的应用程序,设计用于抵御错误。Erlang使用一种称为Actor模型的抽象来处理并发性 - http://en.wikipedia.org/wiki/Actor_(programming_language)。与更传统的共享内存方法不同,Actor之间通过发送消息进行通信。与线程不同,Actor被设计为轻量级,并且消息传递抽象适用于相同或不同机器上的Actor。WhatsApp的简单实现可以是:每个用户/设备都表示为一个Actor。该Actor负责处理用户的收件箱、如何将其序列化到磁盘、用户发送的消息和接收的消息。假设Alice和Bob在WhatsApp上是朋友,那么就有一个Alice Actor和一个Bob Actor。
    让我们跟踪一系列来回流动的消息:
    - Alice决定给Bob发送消息。Alice的手机建立与WhatsApp服务器的连接,并确定此连接绝对来自于Alice的手机。Alice现在通过TCP发送以下消息:“给Bob:一只巨怪正在攻击金门大桥”。其中一个WhatsApp前端服务器反序列化此消息,并将此消息传递给名为Alice的Actor。 - 名为Alice的Actor决定将其序列化并存储在名为“Alice的已发送消息”的文件中,存储在复制的文件系统中以防止由于不可预测的怪物暴动而导致的数据丢失。然后,名为Alice的Actor决定通过向Bob Actor传递消息“来自Alice的Msg1:一只巨怪正在攻击金门大桥”将此消息转发给Bob Actor。名为Alice的Actor可以使用指数退避重试,直到Bob Actor确认接收到该消息。

    演员鲍勃最终收到来自(2)的消息并决定将此消息存储在名为“鲍勃收件箱”的文件中。一旦它已经持久地存储了这个消息,鲍勃会发送一条自己的消息给演员艾丽斯,说“我收到了Msg1”。演员艾丽斯现在可以停止重试。然后鲍勃检查鲍勃的手机是否与服务器有活动连接。是的,所以演员鲍勃通过TCP将该消息流式传输到设备。

    鲍勃看到这条消息后回复说“给艾丽斯:让我们创造巨型机器人来对抗它们”。现在按照步骤1概述,鲍勃演员接收到这条消息。然后鲍勃演员重复步骤2和3,以确保艾丽斯最终接收到将拯救人类的想法。

    实际上,WhatsApp使用XMPP协议而不是我上面概述的优秀协议,但你知道我的意思。


    很好的解释。请分享更多关于这个的链接。 - Rinku

    32
    据我所知,Ejabberd (http://www.ejabberd.im/) 是XMPP服务器的鼻祖,提供了相当不错的开源功能。WhatsApp使用了一些修改过的版本,Facebook消息也使用了修改后的版本。还有一些聊天应用程序,如三星的ChatOn、Nimbuzz Messenger都使用基于ejabberd的解决方案。Erlang解决方案也有这个被重命名为MongooseIM的ejabberd修改版,声称具有高度可扩展性和经过更多性能改进的测试。
    与其他服务器相比,Ejabberd是实现了大部分功能的服务器。由于它是在Erlang中构建的,因此它在水平方向上具有高度可扩展性。

    1
    MongooseIM是一个旧版ejabberd的分支。关于ejabberd在13.x版本后具有更好的可扩展性的说法并不正确。ejabberd使用二进制来减少内存消耗,并且现在拥有更多的功能。这是您最佳的选择。 - Mickaël Rémond
    15.x版本中的可扩展性问题已经解决了吗? - Talespin_Kit
    1
    是的,正如我早就说过的那样。我们在13.x中引入了二进制结构。当然,我们每次发布都会带来更多的性能改进。您可以使用ejabberd 15.x实现巨大的规模(我们为客户做到了这一点)。 - Mickaël Rémond

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接