IM/XMPP服务器选型

一、IM协议选型


IM协议按照是否公开可以分为私有协议(腾讯QQ)和开放协议(GTalk)。私有IM协议需要从零开始设计和搭建,时间和财力成本极高。而开放协议:1)经过业界的长期研究和验证,在安全性、完备性容、容错性等诸多方面都有保障。2)由于其开放的特性,业界已经有很多优秀的开源IM Server和IM Client,直接基于这些开源组件进行开发,可以在相对短的时间内快速搭建高质量的Chat基础服务。3)开放协议一般具有较高的可扩展性,可以进行协议的扩展和改造,以适应特殊的应用场景和需求。


目前主流的IM协议有XMPP (Extensible Messaging and Presence Protocol), SIMPLE(session initiation protocol for instant messaging and presence leveraging extensions), IMPP (Instant Messaging and Presence Protocol).


IMPP主要定义了必要的协议和数据格式,用来构建一个具有空间接收、发布能力的即时信息系统。到目前为止,这个组织已经出版了三个草案RFC,但主要的有两个:一个是针对站点空间和即时通讯模型的(RFC 2778);另一个是针对即时通讯/空间协议需求条件的(RFC2779)。RFC2778是一个资料性质的草案,定义了所有presence和IM服务的原理。RFC2779定义了IMPP的最小需求条件。另外,这个草案还就presence服务定义了一些条款,如运行的命令、信息的格式,以及presence服务器如何把presence的状态变化通知给客户。


SIMPLE计划利用SIP来发送presence信息。SIP是IETF中为终端制定的协议。SIP一般考虑用在建立语音通话中,一旦连接以后,依靠如实时协议(RTP)来进行实际上的语音发送。但SIP不仅仅能被用在语音中,也可以用于视频。SIMPLE被定义为建立一个IM进程的方法。SIMPLE在2002年夏季得到额外的信任,目前,微软和IBM都致力于在它们的即时通讯系统中实现这个协议。 SIMPLE小组致力于进程模式的操作,这将提升运行效率,使基于SIP的机制能够进行会议和三方电话交谈控制,也考虑到能和未来提供的许多新特性实现兼容并提升表现能力。有了进程模式,SIMPLE使用SIP来建立一次进程,再利用SDP(进程描述协议)来实际传输IM数据。


XMPP是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线现场探测。这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。它继承了在XML环境中灵活的发展性。因此,基于XMPP的应用具有超强的可扩展性。经过扩展以后的XMPP可以通过发送扩展的信息来处理用户的需求,以及在XMPP的顶端建立如内容发布系统和基于地址的服务等应用程序。而且,XMPP包含了针对服务器端的软件协议,使之能与另一个服务器进行通话,这使得开发者更容易建立客户应用程序或给一个配好系统添加功能。


XMPP应用广泛,国内外已有众多大规模的应用案例,参见表1。基本上,除了商业公司私有化的聊天协议,XMPP已经成为事实上的标准IM协议。


表1 XMPP应用一览表

公司

产品

Google

Hangouts (前身是GTalk)

Apple

Apple Push Notification Service

iMessage

WhatsApp Inc

WhatsApp (customized)

腾讯

微信 (参考XMPP+ActiveSync)

小米

米聊

深圳市和讯华谷

极光推送

环信

环信


基于XMPP的方案拥有大量的Server端、Client端以及类库实现,可以快速搭建满足业务需求的应用。


XMPP去中心化的设计具有天生的scale out扩展性,同时支持server-2-server通信,可以与其他XMPP服务器进行连接,实现帐号的跨域聊天。XMPP的这种特性非常适合应用于提供IM基础服务的平台。


综上所诉,XMPP是以上几个协议中最完善、可扩展性最好、应用最广、组件支持最多的一个协议。因此,Chat Service选用XMPP作为Chat Service的IM协议。


二、XMPP Server选型


XMPP Server拥有众多的实现方案,参见表2.


表2 XMPP Server实现方案


Name

Platform(s)

License

Details

Latest Release

Apache Vysper

Windows / Linux

Apache License Version 2.0

mina.apache.org

2011-02-23

Citadel

Linux

GPL3

citadel.org

2013-08-14

CommuniGate Pro

Linux / Mac OS X / Windows

Commercial

communigate.com

2013-09-10

Coversant SoapBox Server

Windows

Commercial

coversant.com

unknown

djabberd

Linux

GPL3

danga.com

2011-06-13

ejabberd

Linux / Mac OS X / Solaris / Windows

GPL2

process-one.net

2013-06-28

IceWarp

Linux / Windows

Commercial

icewarp.com

2012-12-11

iChat Server

Mac OS X

Commercial

apple.com

2012-07-25

in.jabberd

Linux

GPL2

inetdxtra.sourceforge.net

2013-05-16

Isode M-Link

Linux / Solaris / Windows

Commercial

isode.com

2013-06-24

jabberd 1.x

Linux

GPL2

jabberd.org

2012-06-28

jabberd 2.x

Linux / Solaris / Windows

GPL2

jabberd2.org

2012-08-26

Jabber XCP

Linux / Solaris / Windows

Commercial

cisco.com

2008-10-31

Jerry Messenger

Linux / Windows

Commercial

j-livesupport.com

unknown

Kwickserver

Windows

GPL

kwickserver.info

2010-10-15

Metronome IM

Linux / Mac OS X

ISC/MIT

lightwitch.org/metronome

2013-10-02

MongooseIM

Linux / Mac OS X

GPL2

erlang-solutions.com

2013-05-23

Openfire

Linux / Mac OS X / Solaris / Windows

Apache

igniterealtime.org

2013-05-28

Oracle Communications Instant Messaging Server

Linux / Solaris / Windows

Commercial

oracle.com

2013-05-07

Prosody IM

Linux / Mac OS X / Windows

MIT/X11

prosody.im

2013-09-10

psyced

Linux / Mac OS X / Windows

GPL2

psyced.org

2011-11-22

Siemens OpenScape

Linux

Commercial

siemens-enterprise.com

2011-12-15

Tigase

Linux / Solaris / Mac OS X / Windows

AGPL

tigase.org

2013-04-24

Vines

Linux / Mac OS X

MIT

getvines.com

2013-06-22

Wokkel

Linux / Solaris / Mac OS X

MIT

wokkel.ik.nu

2013-01-12

其中,较为成熟,且使用广泛的是ejabberd, jabberd 2.x, Openfire, Tigase(蓝底标出). 这几个Server的详细比较可以参考这两篇文章:Choosing An XMPP Server, Android Push 开源方案解析. 以上两篇文章的结论如下:

  1. Jabberd 2.x 使用C语言实现,但是,存在着数据库事务的滥用、内存泄露、不一致的非阻塞设计等问题,最重要的是该server已经很长时间没有人维护;因此,chesspark在使用jabberd 2.x三年后,转用ejabberd。无独有偶,Jabber.org也在2010年淘汰Jabberd, 转为使用ejabberd.

  2. Openfire以及Tigase都是基于JAVA的解决方案。但是极光推送团队认为,Openfire单机并发很有限,集群方案不成熟,代码古老而缺乏及时更新,因此不适合应用在生产环境中。因此,极光团队在初期使用Tigase解决方案。但是在使用中发现,Tigase其集群方案实现复杂,单节点容量有限,后期转为自己开发server.


从编程语言角度看,主流的XMPP Server主要是JAVA和Erlang。JAVA语言的优势是类库完备,容易招人。Erlang的优势是hot code swap, live console, 高并发. ejabberd与Openfire/Tigase比较而言,最大的优势是相对优雅的集群方案以及更高的并发性能。在没有语言偏向性的情况下,一般在开发初期都会选用ejabberd, 如WhatsApp, Facebook Chat, 米聊


从各种XMPP Server支持的特性看,ejabberd是对XMPP协议支持最好、实现最为全面的server.


从开源协议看,Tigase采用AGPL开源协议,因此只要有代码修改,就必须对代码进行开源。Openfire采用Apache开源协议,修改代码后可以闭源。ejabberd采用GPL v2开源协议,如果只在服务端提供服务,而不进行代码二次分发,修改代码以后也可以「闭源」,参考


综合以上各因素,Chat Service采用ejabberd作为初期的XMPP Server.

WhatsApp 公开源代码: http://www.whatsapp.com/opensource/

Chat Secure: https://chatsecure.org/blog/

Public XMPP Server列表:https://xmpp.net/directory.php

可以查看这些server的状态及基本信息(实现方式、认证方式等)。

基于httpd的Erlang Web Server

Background

  1. 有一堆数据需要用Golang来处理,数据是使用Erlang的term_to_binary保存的。
  2. 数据是热数据,因此不能一次性对数据进行binary_to_term预处理。
  3. Erlang的Ports是不太合适的,因为Ports的设计更侧重于Erlang主动与外部进程(一般是其他语言编写的)进行通信。
  4. 基于通用协议使得Golang与Erlang直接可以通信是唯一的出路,通用协议如http, thrift, protobuf等都可以,因此这条出路还挺宽。BERT-RPC强大而笨重,但是没有Golang的RPC Client. 由于需求非常简单,考虑基于Erlang httpd写一个简单的Web Server完成这个任务。

如果不是Erlang, 这个任务应该是分分钟搞定,但是Erlang的官方文档缺乏example, 相关的文章又太少。难怪有人会吐槽:

When I first started using Erlang it took a fair bit of trial and error to create a server that generated dynamic HTTP content. The main problem is the lack of good tutorials out there for doing these kinds of things. The documentation that comes with Erlang is good for reference, but is not that helpful if you’re just learning the language.

How

下面是将用户输入的内容返回给用户的echo server代码:

  1. httpd实现了一套处理http request的behavior, 通过配置可以设置如何路由这些请求。这里使用esi的方式来处理请求。erl_script_alias依赖mod_esi. 因此{modules,[mod_esi]}不能省去。上例将/esi/echoserver:func交给echo_server:func处理。因此,可以通过 http://localhost:8080/esi/echo_server:echo?abcd你好321 进行测试。
  2. httpd定义了一堆mod_*来处理请求,modules之间的顺序有限制的,启用多个模块需要注意。
  3. mod_esi:deliver()第一段内容必须设置Header:

    Use this callback function to dynamically generate dynamic web content. When a part of the page is generated send the data back to the client through deliver/2. Note that the first chunk of data sent to the client must at least contain all HTTP header fields that the response will generate. If the first chunk does not contain the End of HTTP header, that is “\r\n\r\n”, the server will assume that no HTTP header fields will be generated.

  4. 如果返回的内容有unicode字符,需要使用unicode模块处理,否则浏览器会乱码。

References

[1] Working example for Erlang Server Interface

[2] “Hello World” Webapp in Erlang

$190亿的背后 – WhatsApp架构分析笔记

就架构本身来看,WhatsApp (后简称WA, 哇……)的架构属于“实在是太简单了,没有太多分析的价值”。概括起来就是Erlang on FreeBSD through XMPP.

业务需求决定架构。WA用户从零增长到4.5亿月活的过程中基本没有遇到系统扩展性的问题「昨天宕机三个小时原因也不是系统性能的问题,而是路由器的问题」。一方面由于WA业务比较单一,另一方面也得益于对系统的持续优化。

WA的架构在发展过程中有两个比较有意思的阶段:
1. 从C200K到C2800K「C: 这里特指Connection」。
2. 多媒体处理系统升级与优化。

这两个阶段都是在Rick Reed牵头下完成的。这哥们是个比较有意思的人物:2011年从雅虎跳巢到WA「时机把握得真好!」,当他来到WA的时候,居然不知道Erlang是什么东东。然而,仅仅一年后就交出了一台服务器处理百万并发连接的答卷,两年后已经成为Erlang领域的顶尖专家。这哥们貌似很喜欢足球,两次系统优化都是足球夜激增的流量激发了他upgrade的念想:)。

从C200K到C2800K

优化前,一个节点的连接负载能力约为200K,并面临着用户连接增多时系统过载和失败等问题。系统优化的目标很明确:

  • 将一个节点连接负载能力提高到C1000K
  • 可应对软硬件错误/故障以及突发事件造成的连接激增

所采用的方法详见Rick Reed, Scaling to Millions of Simultaneous Connections, March 30 2012. 简单来说,就是把以前所有系统资源利用不合理以及有更高效解决方式的地方都fix了一遍,然后持续优化和改进。根据Rick Reed的数据,第一轮下来提高到了C1000K,第二轮下来提高到了C2000K,并成功顶住了C2800K的峰值。不过Rick Reed认为承受C3000K也是没有问题的。

一些启示:

  • Erlang拥有良好的SMP扩展性,并行优势很明显(24逻辑核上,>85%的利用率)
  • 系统的资源争用有时候会产生难以置信的内耗。从C200K到C2000K就是通过解决/优化资源争用问题完成的。
  • 对于使用频繁的函数,考虑使用更加高效的实现方式往往能收到”小处大为“的效果(WA中使用更加高效的cpu_timestamp,os:timestamp取代erlang:now。对于一个消息系统来说,这两个函数的优化很有意义)
  • 不要忘了客户端App的优化
  • 整个系统的性能取决于木桶最短的那根。很多时候,语言都很难成为最短的那根。当然,更没有必要因为WA是用Erlang构建的,你要把自己的系统转到Erlang上来。

多媒体处理系统升级与优化

最开始,系统是基于lighttpd + PHP. 为了让这个子系统具有更好的扩展性、稳定性以及用户体验,Rick对他进行了一次Erlang化改造。详细参见Rick Reed, March 21 2013。升级或的架构图如下图所示:

wa_mms

数据存储方面,垂直和水平都做了分片:

wa_db_sharding

新架构下的系统峰值性能:

  • 214M images in a day
  • 8.8K images/sec downloades
  • 29 Gb/sec output bandwidth

 

WA被收购后,Rick在Erlang Factory做了一次分享,这次分享的总结可以参加这篇文章,强烈建议有时间研究一下。

好啦,WA讲述的根本就不是Brian Acton屌丝逆袭的故事。它讲述的是Rick和Erlang的恋爱史。至此,移动端的IM布局基本也就不会发生大的变化了。在一次对Rick的采访中,有一个问题很有意思:

Mirko: Since you are working for the most used messaging system on the planet I have two non-technical questions. What is from your point of view the best thing introduced by digital communications? And on the other side, what do you miss from the “paper and pen” communication era?

Rick: Well we’ve come a long way from my first experience with digital communication, email on the arpanet. Today, I’m just a few taps on my smartphone away from instant communication with my family, friends, and coworkers, no matter where they are.

I think the downside is that because there are so many ways to communicate (phone, voicemail, email, messaging), you almost have to establish a mapping between each of the people and organisations in your life and how best to communicate with them. And if you get the mapping wrong, the mismatch between what you expect and they expect can cause all kinds of trouble.

小龙和企鹅看完会心一笑。

 

参考:How WhatsApp Grew To Nearly 500 Million Users, 11,000 Cores, And 70 Million Messages A Second