解剖 Twitter【8】得过不且过
北京西直门立交桥的设计,经常遭人诟病。客观上讲,对于一座立交桥而言,能够四通八达,就算得上基本完成任务了。大家诟病的原因,主要是因为行进路线太复杂。
当然,站在设计者角度讲,他们需要综合考虑来自各方面的制约。但是考虑到世界上立交桥比比皆是,各有各的难处,然而像西直门立交桥这样让人迷惑的,还真是少见。所以,对于西直门立交桥的设计者而言,困难是客观存在的,但是改进的空间总还是有的。
Figure 10. 北京西直门立交桥行进路线
Courtesy http://farm3.static.flickr.com/2671/4113112287_86cfb1cffd_o.png
大型网站的架构设计也一样,沿用传统的设计,省心又省力,但是代价是网站的性能。网站的性能不好,用户的体验也不好。Twitter 这样的大型网站之所以能够一飞冲天,不仅功能的设计迎合了时代的需要,同时,技术上精益求精也是成功的必要保障。
例如,从 Mongrel 到 MemCached 之间,需要一个数据传输通道。或者严格地说,需要一个 client library communicating to the memcached server。Twitter 的工程师们,先用 Ruby 实现了一个通道。后来又用 C 实现了一个更快的通道。随后,不断地改进细节,不断地提升数据传输的效率。这一系列的改进,使 Twitter 的运行速度,从原先不设缓存时,每秒钟处理 3.23 个请求,到现在每秒处理 139.03 个请求,参见 Figure 11。这个数据通道,现在定名为 libmemcached,是开源项目 [38]。
Figure 11. Evolving from a Ruby memcached client to a C client with optimised hashing. These changes increases Twitter performance from 3.23 requests per second without caching, to 139.03 requests per second nowadays [14].
Courtesy http://farm3.static.flickr.com/2767/4115077218_55c7250d43_o.png
又例如,Twitter 系统中用消息队列来传递控制信号。这些控制信号,从插入队列,到被删除,生命周期很短。短暂的生命周期,意味着消息队列的垃圾回收 (Garbage Collection) 的效率,会严重影响整个系统的效率。因此,改进垃圾回收的机制,不断提高效率,成为不可避免的问题。Twitter 使用的消息队列,原先不是 Kestrel,而是用 Ruby 编写的一个简单的队列工具。但是如果继续沿用 Ruby 这种语言,性能优化的空间不大。Ruby 的优点是集成了很多功能,从而大大减少了开发过程中编写程序的工作量。但是优点也同时是缺点,集成的功能太多,拖累也就多,牵一发而动全身,造成优化困难。
Twitter 工程师戏言,”Ruby 抗拒优化”,(“Ruby is optimization resistant”, by Evan Weaver [14])。几经尝试以后,Twitter 的工程师们最终放弃了 Ruby 语言,改用 Scala 语言,自行实现了一个队列,命名为 Kestrel [39]。
改换语言的主要动机是,Scala 运行在 JVM 之上,因此优化 Garbage Collection 性能的手段丰富。Figure 12. 显示了使用 Kestrel 以后,垃圾回收的滞后,在平时只有 2ms,最高不超过 4ms。高峰时段,平均滞后 5ms,最高不超过 35ms。
Figure 12. The latency of Twitter Kestrel garbage collection [14].
Courtesy http://farm3.static.flickr.com/2617/4115072726_c611955bb2_o.png
RubyOnRails 逐渐淡出 Twitter,看来这是大势所趋。最后一步,也是最高潮的一步,可能是替换 Mongrel。事实上,Twitter 所谓 “API Server”,很可能是他们替换 Mongrel 的前奏。
Twitter 的 Evan Weaver 说,“API Server” 的运行效率,比 Apache+Mongrel 组合的速度快 4 倍。所谓 Apache+Mongrel 组合,是 RubyOnRails 的一种实现方式。Apache+Mongrel 组合,每秒能够处理 139 个请求,参见 Figure 11,而 “API Server” 每秒钟能够处理大约 550 个请求 [16]。换句话说,使用 Apache+Mongrel 组合,优点是降低了工程师们写程序的负担,但是代价是系统性能降低了 4 倍,换句话说,用户平均等待的时间延长了 4 倍。
活着通常不难,活得精彩永远很难。得过不且过,这是一种精神。
Reference,
[14] Improving running component of Twitter.
(http://qconlondon.com/london-2009/file?path=/qcon-london-2009/slides/EvanWeaver_ImprovingRunningComponentsAtTwitter.pdf)
[16] Updating Twitter without service disruptions.
(http://gojko.net/2009/03/16/qcon-london-2009-upgrading-twitter-without-service-disruptions/)
[38] Open source project, libmemcached, by Twitter.
(http://tangent.org/552/libmemcached.html)
[39] Open source project, Kestrel Messaging Queue, by Twitter.
(http://github.com/robey/kestrel)