OpenFeint的系统迁移之路
在今天举行的 RubyConfChina 2012大会上,来自OpenFeint的黄志敏( @flyerhzm)在下午的第一个演讲中为大家带来了OpenFeint平台从REE向JRuby迁移的经验,向大家展示了JRuby带来的巨大性能提升,同时就其中遇到的一些问题进行了分享。
开场时,黄志敏就抛出了一个令人振奋的数据:
JRuby给OpenFeint带来了40%的性能提升!
OpenFeint是最大的移动社交游戏平台,每分钟有几十万API调用,由于起步时间较早,之前一直运行在REE 1.8.7 + Rails 2.3.14的环境之下。为了解决性能问题,他们做了一些方案,其中包含向JRuby迁移,但是由于大多数开发者都没有Java平台的经验,所以这一项并没有被提上较高的优先级。在美国的RailsConf 2012上,大多数人都抱怨Ruby的GC性能很差,在Real World Rails Apps at Massive Scale的讨论中提到了Ruby GC占用了大量的系统资源,而在其他两个演讲中讲到了JRuby带来种种好处,于是OpenFeint决定开始他们的迁移之路。
在开始前,他们做了一个简单的快速性能测试,在一台测试服务器上(memcached、redis和rabbitmq等软件都运行在一台机器里),禁用了mysql sharding、后台任务和其他无法工作的部分,分别运行REE 1.8.7 2010.01(GC未优化) + Passenger和JRuby 1.6.7.2 + Torquebox接受请求,前者响应为331ms,而后者只需51.5ms。虽然这个测试里有很多不足的地方,但是其结果的确鼓舞人心。
OpenFeint的系统栈里主要有以下部分组成:
- 负载均衡
- Web / App Servers
- Mysql
- Memcached
- Redis
- RabbitMQ
- 其他部分
迁移工作主要是将App Servers从Passenger迁移到Torquebox,迁移时希望能尽可能减少人力投入。App Servers根据功能分为多个池,迁移时逐个进行迁移,在每个池里先部署一台。这种做法能更快地享受到JRuby带来的性能提升,能更快地积累经验,但是必须要保证代码能同时运行在REE和JRuby下,带来了一定的运维复杂度。
虽然JRuby与CRuby在语法上没有什么不同,但是两者仍然存在一些不兼容的地方,首先就是要逐步替换不兼容的gem:
- yajl-ruby和hiredis,这两个gem使用了C扩展,在JRuby下C扩展的使用还不理想
- 替换了mysql的驱动
- typhoeus在大压力下,很快就会导致JVM崩溃,因此将它换为了net-http-persistent
- memcached的客户端被替换为jruby-memcached,必须保证REE和JRuby下一致性Hash算法能保持一致,所以没有选择其他方案
出于性能考虑,还要 开启JRuby的threadsafe特性。JRuby往往需要比CRuby更多的内存,因此还需要设置JRUBY-OPTS,调整JVM堆等一些配置,比如将Xmx从默认的512M提高到2G, 提供更大的CodeCache。还有一些问题也会造成性能下降,例如 ActiveRecord 2.3.14是线程不安全的,大并发下容易造成死锁,导致吞吐量下降。
他建议在开发和测试环境中使用CRuby,在持续集成与线上环境使用JRuby。目前有以下一些可选的JRuby部署环境:
- Trinidad,基于Tomcat
- Torquebox,基于JBoss AS(运行速度更快,有团队进行维护)
- Mizuno,基于Jetty
- Puma,这是一个新的Ruby Server(Rack版本很高)
最后,OpenFeint选择了Torquebox-lite,这是一个仅包含Web模块的Torquebox精简版,可以通过配置进行扩展。Torquebox-lite也像Passenger一样,可以进行热部署,只需简单的一句touch就可以了,但是每次热部署时会造成一定的停顿时间,而且每次热部署后非堆内存都会增加,所以最后他们还是选择了逐台重启服务的策略。
在经过了一些的调整之后,OpenFeint的同学们又进行了一次较为正式的性能测试,在线上的备机上进行测试,结果毫无悬念是JRuby胜出。对比Ruby 1.9.3p194 + Passenger和JRuby 1.7.0RC2 + Torquebox-lite,读操作耗时分别为374ms和187ms,写操作耗时分别为42ms和38ms。整体的性能提升在40%左右,不同的应用服务器池情况稍有不同,但总体上都有30%以上的提升。在使用过程中,他们禁用了JRuby 1.7的invokedynamic特性,原因是开启该特性后Torquebox无法正常运行,相信在修正这个问题后,启用该特性会有更大的性能提升。
一个运行生产环境的系统自然少不了监控,在使用REE时,OpenFeint的监控主要用NewRelic和Scout,迁移到JRuby之后,还是使用NewRelic,Scout需要加上JMX Monitoring Plugin插件。此外,JRuby的监控还有一些工具,比如命令行下的jstat、jstack和jmap,图形化的jconsole和visualvm。黄志敏还介绍了几个他自己的问题排查经历,就是使用这些工具进行的。
JRuby最近刚发布了1.7.0正式版,相信随着JRuby的不断发展,以及Java平台的不断升级,JRuby将会被越来越多的人用于生产环境之中,有兴趣的读者可以访问 JRuby的官方网站了解进一步的信息。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至 [email protected]。也欢迎大家通过新浪微博( @InfoQ)或者腾讯微博( @InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。
丁雪丰 是InfoQ中文站编辑,满江红翻译组核心成员,出版过《Spring攻略》、《JRuby实战》等多部译著。主要关注领域:企业级应用、海量数据计算、动态语言应用等。