写点什么

范凯观点:Ruby 社区应该去 Rails 化

  • 2013-03-28
  • 本文字数:2821 字

    阅读完需:约 9 分钟

InfoQ 中文站报道过一些公司从 Ruby 转移到其他语言的新闻,包括 Iron.io 从 Ruby 迁移到 Go:减少了 28 台服务器并避免了连锁故障从Ruby 向Java 的迁移帮助Twitter 挺过了美国大选在LinkedIn 的Ruby on Rails 和Node.js 对决。最近,IT 元老范凯在博客中详细地分析了Rails 目前在Web 服务方面的局限和原因,针对“继续沿用Ruby on rails 重写或者重构应用,性能可能会有一两倍的提升,但无法弥合10 倍以上的性能差距,难道说Ruby 真的如此不堪吗?注定要被Node.js 或者Go 所取代吗?”这个问题给出了自己的观点,即:使用其他Ruby 轻量级框架取代Rails,而不是使用Node.js 和Go 取代Ruby。

针对Ruby 的性能问题,范凯首先做了澄清,存在性能问题的是Rails,而不是Ruby 语言本身,他引用了Ruby 的纤程框架 Goliath 的实际应用数据:

  • VPS 上总共使用了 16 个 CPU 内核,跑了 16 个单进程实例
  • 每个进程实例稳定消耗 50MB 内存
  • Web 框架使用 Goliath, URL 分发是 grape,数据库访问使用 ActiveRecord,缓存使用 Redis
  • 应用吞吐量达到了 1800 request/s

这个数据意味着一台配备了 4 颗 4 核 CPU,2G 内存的服务器,每天可以处理 1.5 亿次 web 请求。由此可见,Ruby 完全可以做到高并发 IO 的应用。问题主要不在 Ruby 解释器上,而在 Rails 框架上。更准确的说就是, Ruby on R****ails 作为一个 full-stack 的 web 开发框架,并不适合用来开发 Linkedin 和 Iron.io 的后台 web 服务,从某种意义上来说,属于 Rails 的时代已经过去了。

范凯表示:移动时代,Web 服务将取代 Web 网站。为什么 Rails 不适合 Web 服务呢,他认为主要原因包括:

  • Rails 调用堆栈过深,URL 请求处理性能很差Rails 的设计目标是提供 Web 开发的 最佳实践 ,所以无论你需要不需要,Rails 默认提供了开发 Website 所有可能的组件,但其中绝大部分你可能一辈子都用不上。其中最夸张的是ActionDispatch::RequestIdmiddleware,只有在大型应用部署在群集环境下进行线上调试才可能用到的功能,有什么必要做成默认的功能呢? Rails 的哲学是:提供最全的功能集给你,如果你用不到,你自己手工一个一个关闭掉 ,但是这样带来的结果就是默认带了太多不必要的冗余功能,造成性能损耗极大。
  • Rails 加载的框架和依赖库过多,内存消耗过度。Rails 自身依赖库非常多,造成的结果就是 Rails 应用持续运行以后内存消耗非常高。举个例子:如果你用到了 Rails 的 asset pipeline 功能,那么项目需要依赖一个 JS 引擎来编译 JS 和 CSS,默认会使用 libv8 这个库。尽管只是编译阶段使用 libv8,运行期并不需要它,但是仍然会加载 libv8,这意味着你的每个 ruby 进程会多占 20MB 内存。在我们其中一个大项目上,总共开了 40 个 Ruby 进程,直接浪费了 800MB 内存。于是我们不得不在生产服务器上安装了 Node.js,替换了 libv8。此外,一旦其中某个依赖库有内存泄露,整个应用也可能出现内存泄露,这种内存泄露是很讨厌的事情,Rails 如此肆无忌惮不加限制的使用第三方依赖库也是一个潜在的隐患。
  • Rails 传统多进程模型的 IO 并发能力很低。Rails 的多进程并发模型的 IO 并发能力很低,开多少个进程,就只能同时响应多少个并发请求,但 Ruby 进程的内存消耗是很大的,多进程调度的 CPU 开销也很高,这决定了单台服务器上能开的进程数是非常有限的,一般不会超过 30 个。但是对于 Web Service 类型的应用,需要很高的 IO 并发处理能力,传统 Rails 多进程很容易就会出现负载的瓶颈。从 Rails4.0 开始,默认也开启了多线程模式,也可以支持多线程方式运行 Rails 应用。但就目前来说,Rails 使用多线程,还面临一些兼容性问题:大量的 Rails 插件和代码不是线程安全的,在多线程模型下运行,会出现意想不到的 bug;另外 Rails 的多线程应用尚未得到广泛应用,可能会有潜在的 bug。

不用 Rails,Ruby 社区又能用什么呢?范凯提供了自己的建议:

  • Sinatra ——Sinatra 本身也是 Ruby 社区非常流行和著名的轻量级 Web 框架,核心源代码不超过 1000 行,文档只有 1 页。对于 Rails 开发者来说,花了几个小时,就可以快速使用 Sinatra 开发 Web Service 了。Sinatra 对多线程支持的非常好,可以用 rainbows 来跑多线程 Sinatra,IO 并发处理能力很好。Github 也是用它来提供开放 API 服务的。我自己写了一个 Sinatra 的项目模版,如果你用 Sinatra 开发 Web Service,可以参考。
  • Padrino ——Padrino 是一个基于 Sinatra 之上的轻量级 Web 框架,在 Sinatra 基础之上提供了命名路由,模块化项目组织,页面 helpers 和 generators 等等。Padrino 是一个高度模仿 Rails 的框架,API 的命名和 Rails 很像,Rails 开发者花 1-2 天看看文档就可以快速上手开发了。Padrino 相比 Rails 易学易用,多线程支持良好,性能比 Rails 好很多,开发 Website 推荐使用。我自己的网站也是用 Padrino 开发的,源代码在: robbin_site
  • Goliath ——Goliath 是一个 Ruby 的纤程开发框架,性能非常好,作者本身是在开发 PostRank 产品过程中开发的 Goliath。PostRank 是一个用户社交行为实时跟踪工具,需要很高的性能来支撑,PostRank 被 Google 收购了,作者现在在 Google 工作。Goliath 适合用来开发对性能非常敏感的 Web Service 或者 real-time 的应用,但使用 Goliath 有一些门槛,你不能使用普通的阻塞 IO 库,必须使用作者封装的一些纤程的库。

所谓的“去 Rails 化”,范凯认为不必大惊小怪:

学习 Rails 无非意味着你花了时间熟悉 ActiveRecord 和 ActionPack 以及相关库的功能而已,所谓去 Rails 化也仅仅只是放弃使用 ActionPack,换一个更轻量级更简单的 URL 路由处理器,例如换成 Grape,Sinatra,Padrino 或者 Camping 而已。这对一个长期使用 Rails 的 Ruby 开发者来说,应该是举手之劳的事情。所以自己动手,根据实际应用场景挑选最合适的组件。例如 ActionPack 不太适合写 Web Service,那我换成 Sinatra 就行了,但是 ActiveRecord 照常用,这并不需要你付出多少学习成本,更不需要你放弃什么。

目前有一些公司从 Ruby/Rails 转向 Node.js 和 Go,范凯经过调研,认为 Ruby 更适合自己:

  • 用 Sinatra 或者 Goliath 这样的轻量级框架写 Web Service,性能已经足够好了,特别是 @黄志敏的案例证明,16 核已经可以支撑每天 1.5 亿次请求了,对我来说已经不太可能遇到超过这个负载量的应用了。而 Ruby 的开发效率,代码表达能力和可维护性对我来说还是很重要的。
  • Node.js 的 Event IO 编程风格在我看来是“反人类”的,极其变态的。用来写代码上规模的应用,代码的可读性和可维护性都很差。Event IO 是很底层的技术,我很难理解为何不封装成 coroutine 来使用。Node.js 只适合用来开发 real-time 类型的应用。
  • Go 的主要问题在于现阶段还不成熟:一方面 Go 自身还在演进当中;另一方面 Go 的类库还是过于贫瘠了,用来开发项目还是需要自己写很多东西的,感觉很不方便。

有关范凯完整的论述,可以查看博客原文。欢迎 InfoQ 读者发表自己的看法。

2013-03-28 01:094872
用户头像

发布了 501 篇内容, 共 248.0 次阅读, 收获喜欢 57 次。

关注

评论

发布
暂无评论
发现更多内容

一文带你了解 「图数据库」Nebula 的存储设计和思考

NebulaGraph

数据存储 图数据库

5年从初学者变成行业大拿,月薪暴涨10倍,我的经验值得借鉴

爱好编程进阶

程序员 后端开发

CCF201712-2 游戏

爱好编程进阶

Java 程序员 后端开发

如何将知识管理应用到工作中,解决企业的问题?

小炮

图片

武师叔

技术揭秘 | 阿里云EMR StarRocks 线上发布会预约开启!

阿里云大数据AI技术

StarRocks 产品发布会

09-SSO微服务工程中用户行为日志的记录(2107~2108~2109

爱好编程进阶

Java 程序员 后端开发

2021字节、阿里大厂高频面试真题1000道(附答案解析

爱好编程进阶

Java 程序员 后端开发

Backbone 之 DetNet:为检测而生(Pytorch实现及代码解析

爱好编程进阶

Java 程序员 后端开发

B站【狂神说Java笔记】-java基础语法

爱好编程进阶

Java 程序员 后端开发

官宣|Apache Flink 1.15 发布公告

Apache Flink

大数据 flink 编程 流计算 实时计算

[Day38]-[二叉树]-二叉树的右视图

方勇(gopher)

LeetCode 二叉树 数据结构算法

全球最大的半导体IP产业链,你了解多少?

Finovy Cloud

gpu GPU服务器 显卡、gpu

养殖场新来了个“AI管家”

华为云开发者联盟

hilens ModelArts Pro 养殖场 AI摄像头 天视通

2020最后一次Java面试,快手三面一轮游,如今已拿意向书

爱好编程进阶

Java 程序员 后端开发

2022年Java面试题最新整理,附白话答案

爱好编程进阶

Java 程序员 后端开发

43岁老程序员的编程之路,我是如何做到退休的?龙叔真的退休了吗

爱好编程进阶

Java 程序员 后端开发

CRMEB Java.小程序交易组件操作使用教程

CRMEB

银丰新融:搭建名单监控管理系统,落实“三反”政策

华为云开发者联盟

安全 GaussDB 反洗钱 名单监控管理系统

java培训分布式和集群的区别

@零度

分布式 JAVA开发 集群

CentOS7 部署 LAMP 平台与应用

爱好编程进阶

Java 程序员 后端开发

安全领导力| GitLab 持续位列 Gartner AST 魔力象限

极狐GitLab

安全

Java 基础语法

源字节1号

软件开发 前端开发 Java后端 小程序开发

6年,终拿腾讯 offer!

爱好编程进阶

程序员 后端开发

IDC Panel:智能运维在金融行业中的场景化应用

BizSeer必示科技

OceanBase 源码解读(十):一号表及其服务寻址

OceanBase 数据库

oceanbase 源码解读

火山引擎推出基于全新视角的 Web 端性能监控方案

字节跳动终端技术

字节跳动 Web 性能监控 火山引擎

面试中被问到最多的 19 个 JavaScript 问题

海拥(haiyong.site)

JavaScript 5月月更

七、高可用之故障演练

穿过生命散发芬芳

故障演练 5月月更 高可用设计

web前端培训项目的 Vite 迁移实践分析

@零度

前端开发 vite

Bootstrap表格

爱好编程进阶

Java 程序员

范凯观点:Ruby社区应该去Rails化_Ruby_崔康_InfoQ精选文章