• Feeds

  • 多服务器通讯层应该如何设计—一次code review小记

    大型的网络应用服务器(比如即时通讯及游戏服务器等)通常有大量的服务器内部数据通讯需求,几个月前曾经介绍过通讯层的实现再谈点对点通讯模块的故障问题,目前这个程序已经经历了数个版本的重构。今天进行了一次小组code review,讨论了当前版本的一些问题。

    I. Background

    我们为什么需要一个独立的通讯层

    对于服务器内部的通讯功能,已经有TCP提供可靠传输,已经有类似Apache MINA这样的框架来提供上层的封装,业务逻辑代码完全可以直接基于socket或MINA这样的框架来直接传送数据,我们为什么还需要包装一个独立的通讯层?

    目前考虑到的原因有

    • Connection pool作用。为了节点间更高的throughput, 通常两节点之间会使用n个固定连接来传输。n可设为CPU内核数大小。
    • 多节点互相连接的处理。一个节点需要连接n个节点发送信息。如果这部分逻辑放在业务调用层来实现,业务层会变得臃肿。
    • 处理自动重连逻辑,单个节点可以停用并重新启用。将这部分逻辑封装到通讯层,上层调用会更优雅。
    • 服务器之间通讯很短时间内不稳定(比如10s左右的中断)的处理。如果IDC内部或IDC之间通讯不稳定会造成这种现象。我们希望这种短暂的中断,不要引起业务逻辑重新选择节点,造成大量数据迁移及cache重构带来的内部振荡。
    • 海量数据传输最优化,大部分时间单个节点单向传输会>10k个数据包/s,独立的通讯层容易测试观察该环节是否存在瓶颈。

    通讯层不做什么

    • 序列化/反序列化,这个通常使用其他的框架或技术来做,比如protocol buffers, json等
    • RPC, 我们不做rpc的事情,已有的各种RPC技术已经做得足够好了,如果有RPC需求,我们会使用其他现有的技术。

    II. Code Review过程

    逻辑介绍

    首先由主程介绍了目前的数据流程,架构图及核心代码片断。比较核心的重发机制图示意如下

    comm

    (Figure 1: 重发的流程)

    过程说明:

    • 每个数据包有个TTL值,TTL>0之前会一直重试发给同一节点。这主要避免短期网络中断带来集群内振荡。
    • 如果正常的节点投递失败,则继续投递到backup节点。Backup节点由调用方在投递时候指定。类似在邮政寄快递,需要填写如果投递不到收件人怎么处理。通讯层只是根据投递地址表(list)来进行二次投递。
    • 如果backup也失败,则返回调用方的callback FailureHandler。这点有点类似Erlang里面失败处理的思路。

    听众提出的问题

    • 重发那一段流程是否必要,因为TCP本身已经有重发逻辑。应用层再加上一层重发处理,原理上可以应付短暂的网络中断,但是实际运行过程中能否真正有很大效果。(目前运行的情况也没有很明确的数据来支持这一点)
    • 目前一个节点需要连接的多个节点是静态配置的,即由程序启动时候决定,没有做自动发现及删除。目标节点是否可用由发送方自行判断。因此提出一个问题,backup节点选择由调用方来指定是否最佳?可否让通讯层自动协商,内部选择另一个同一类型的节点来做替代节点?但实现通讯层节点自动协商机制会增加程序复杂度。毕竟我们不是P2P程序,节点故障发生的情况很少。因此需要综合来权衡。
    • 目前的结构处理几十到上百个节点的集群问题不大,如果要用在上千个节点的场合,有哪些环节需要调整?

    其他提出的一些问题是针对具体代码写法的,由于不具有广泛借鉴意义,就不一一赘述。

    搜狐IM

    一直认为几大门户中只有搜狐没有做IM,实际上sohu也有个类似的WebIM产品,名字起得有点误导,叫搜狐小纸条。可能是在纸条箱的基础上增加了在线状态等功能,最终变成了一个准IM。在它官方的说明中是这样描述

    搜狐小纸条及聊天室是搜狐公司 ChinaRenTeam 自主研发的Web即时聊天工具它服务于所有搜狐用户, 并不断努力为更多网友提供便捷快速的聊天体验!
    它直接在网页登录, 页面打开,直接聊天. 无需下载任何客户端和插件
    请记住我们的网址:http://me.sohu.com
    请记住我们的名字:搜狐小纸条!

    这个系统由ChinaRen网站总监邹丹主导开发,它的系统核心架构在邹丹的网站描述如下

    OnlineServer:
    ChinaRen/SOHU小纸条系统核心

    核心为3个小server系统:online2(在线系统业务逻辑),userv(用户资料系统),cserv(LRU缓存) 这三个子系统都是UDP+线程池结构,单进程+多线程。配备java接口,apache_mod的json和xml接口。 online2包括了大部分业务逻辑,包括,上线,好友系统,纸条系统。 userv包括设置用户各种属性,信息。 cserv是个大的lru缓存,用于减小磁盘IO。可以放各种信息块,包括用户信息,好友,留言等。 目前配备4台服务器(DL380,xeon:3G*2,SCSI:146G raid,Ram:2G),用户分布到4台服务器上,相互交互。服务器可以由1台到2台,到4台,到8台。 底层存储为文件存储(无数据库),用reiserfs。 配套系统: mod_online,两个版本,apache和lighttpd版本,用于页面上显示蜡烛人。请求量巨大,目前用lighttpd版本的mod_online。 放在sohu的squid前端机器上,运行在8080,大概8台,每台请求量大概500-800个每秒。蜡烛人在所有ChinaRen页面有ID的地方 显示用户是否在线。 目前这套在线系统,作为SOHUIM的内核原型。准备开发WEBIM系统,用户所有SOHU矩阵用户的联络。

    总结一下:
    门户的核心服务,要求是高效率,高密度存取,海量数据,最好还是低成本。不要用数据库,不要用java,不要用mswin。用C,用内存,用文件,用linux就对了。

    据未经证实的消息来源了解到,Sohu的整套IM架构使用了150台左右的服务器。其中接入服务器,Web服务器,后台服务器各占1/3左右。

    另外从邹丹的网站了解到,他还是一位QQ黑客,从2000年开始就曾经开发过数版的QQ显IP插件,以及Linux下实现QQ协议的Gaim(Pidgin)插件,可惜去了ChinaRen之后就停止了这方面的研究。从他的网站依稀可以看到2000年左右国内流行的个人主页的风格。

    5%的神话(关于开发效率与职业方向)

    Bruce Eckel(Thinking in Java/C++作者) 在他的 5%的神话 (Mythical 5%) 中提到:

    5%的程序员开发效率是其他95%程序员的20倍

    (5% of programmers are 20x more productive than the other 95%)

    按照80-20法则,80%的程序员几乎不看书,不读Blog,不参加技术会议,不持续学习。这些人也可能会进入大公司,他们日复一日的做着重复的 工作。另外20%则在专业方面比较主动,他们喜欢阅读,喜欢学习,喜欢参加技术活动。这20%当中又会有80%的人可能不会特别成功,他们仍然走在通往成 功的路上奋斗。剩下20%,也就是总数的5%的开发人员具备20倍的开发效率。

    那如何成为这5%中的一员呢

    Bruce Eckel 的观点:阅读,分析,总结,实践

    这5%的人会习惯经常阅读新技术,并喜欢参与各种有潜在价值的新概念的实践,他们会有非常有选择性的参与会议,大部分时间都花在有效率的事情上,将事情做成。

    要想比别人效率高出20%,则需要在各个方面达到平衡,而不单只是能将事情搞定那么简单,因此你要使用最好的工具,最优秀的技术,并尽最大的努力。平衡点并 不是从明显的事物上就可以轻松获得,或者是被人告知的经验,或者是大众化的经验。它需要自己摸索并发现事物背后的规律,需要自己去总结并发现。

    比如我们通常对各种编程语言优缺点熟记于心,我们通常可以脱口而出比如erlang适合大并发场合等等。但是大部分人不会意识到很多场合语言并不重要。

    因此如果你要成为那5你必须持之以恒的坚持学习,多学习编程是有好处的,但是仅仅局限于了解编程是不够的,比如类似以下经验:

    • 代码被阅读的时间比写代码的时间要长,如果你的代码不能被人理解,则没人会去改善或者修改其中的bug
    • Code review是最有成效的改善软件缺陷的方法,但在我们却经常“没有时间来考虑它”

    所以除了精通编程之外,最好多看一些编程方法与协作的书,如并不传授编程技巧的《代码大全》之类的书。

    Jeff Atwood (Coding Horror) 的观点:技术博客重要性

    当然也有持不同观点者,如Jeff Atwood(coding horror作者)则认为经常分享自己的技术体会比coding更重要,能写的人才能成为那5%。他曾经横穿北美,从美国西岸San Francisco到加拿大的东岸Montreal去给一个大学的学生讲技术Blog的重要性。他在这篇Is Writing More Important than Programming(ppt, 3mb)演讲中提到:

    大部分我景仰的程序员都是通过其blog让我景仰,而不是他的代码

    ……大部分不写blog程序员的理由有:太忙;写了也没人看;没有合适内容可写;觉得自己不善长表达等。

    Jeff Atwood大部分观点我是深表赞同的,可喜的是身边乐于分享的越来越多。比如新浪开发者博客今年2月才开张,现在已经有100多篇高质量文章了。

    另外我很敬佩的TopLanguage创建者刘未鹏也写过一篇很有名的为什么你应该(从现在开始就)写博客,想必很多朋友都看过。

    其他观点

    国内曾翻译过Erlang程序设计的Trustno1则认为这5%的人必须是钻研paper的人, 而只是看看rss,热衷于参加各种技术会议,搞搞各种可替代性很强的技术的人是不够格的,他在某帖子中提到:

    很简单的两个标准.
    标准一,你看到一个问题的第一感觉”这个事情不学3-4年数学算法光靠捣鼓捣鼓API设计模式肯定搞不定”
    案例一,老板让你做一个从视频里识别出人脸的程序.
    标准二,但凡性能Critial又没有现成方案的东西.
    案例二,老板让你做一个实时的全局照明渲染引擎.

    原讨论在这里 http://www.javaeye.com/topic/380651 其中一些观点也是有争议的,不过话题已经被锁定不让讨论了;)

    总结

    想必看了上面这一系列,你对怎样成为那5%已有自己的见解了。你要的答案或许不在这篇文章里,因为Bruce Eckel提到,大部分成为5%的人的经验是只可意会,不可言传的。