分享 又一篇讲为什么从 Python (文中的观点也可以适用于 Ruby) 迁移到 Erlang 的文章

defmacro · 2016年07月07日 · 最后由 JGpirateKing 回复于 2018年06月09日 · 12352 次阅读
本帖已被设为精华帖!

https://ourway.ir/Why_And_How_I_Switched_From_Python_To_Erlang.html

注意我的 Chrome 直接打开这篇会崩不知道为什么,要 Safari 才能顺利打开。

通常情况下对这种文章我是直接忽略的,因为多半是神经病一样的 “看我的 Hello World 请求在 BEAM 下跑的飞快,再看你那慢如狗的 Rails”。。。但是这篇文章说到点子上了,而且很多对于 Python 的论据也适合于 Rails,或者是 Ruby(是的我天天鼓吹的 Cuba 架构也有这个问题)。Rails/Ruby 发展到现在,绝大多数问题都是有解决的方案的,Sidekiq,Russian Doll Caching 等等都是为了解决所谓的慢而出现的。但是在工程圈里,有解决方案并不是唯一的 metric,很多时候我们要考虑投入产出比。虽然用上面的许多方案可以解决 Rails 的问题,但是考虑这样的场景:一个资深工程师充分设计并调优之后的一个 Rails codebase,可能也就是跟一个初学者随便写写的 OpenResty,或者是 node.js 框架跑的差不多快,我不知道大家,这时候我是很有挫败感的。

所以我最近反思的一个主题是:是不是真的有必要追求 Rails/Ruby 那可能只有 10% 或者 20% 的生产力提升,而抛弃整个框架设计层面的许多可能性。这已经不是 Rails 刚出现的那个时代了,现在其他语言的框架 (包括 Java) 也充分吸收了 Rails 的很多优点,生产力也已经大幅提升,Rails 已经没有那种数量级上的差距了 (当然从这个角度来说 Rails 很成功,这个我十分赞同)。说的偏激一点,这 10% 或者 20% 现在是否存在,也是一件有争议的事情,并不是每个人都认同。

当然也不是说 Ruby 就这样完了,我觉得 HTTP/2 就是一个 Ruby 可以利用的好机会,配合 HTTP/2 带有 Push 机制的架构,这正是一个我们反思 Rack 是不是适合 HTTP/2 的机会,完全可以趁这股潮流重新设计 Rack,做一个基于 Fiber 的结构,虽然这样跟 HTTP/1 会有非常大的冲突,但是这给了 Ruby 社区一个可能性:传统项目完全可以继续走 HTTP/1 以及 Rack 1.x 继续走原来的路,如果想做新一代的 web app,这样的全新架构也可以提供跟 OpenResty,Elixir 竞争的底气。

无奈现实不给力,现在 Ruby 社区对 HTTP/2 的使用真的很让人痛心:一部分人在忙着把 Rack 的 API 从 hash-based 改成 object-based,另一部分人把 nginx 换成新版本然后就此标榜 Rails 是 HTTP/2 的了,这是在过家家么 -_-

另外我在广义层面上不赞同 "Right Tool For The Right Job" 的观点。这个观点只适用于大公司,初创企业即使有工程师出身的开发人员,也要身兼数职,更何况很多初创企业是其他行业的人半专职过来写代码,这种情况下面对 HTML/JS/CSS/Ruby 就已经很头痛了,我们还不帮忙把这个 list 减少反而要引入更多的工具,究竟是在做项目还是在玩工具。。。

求大神把我骂醒

很多观点和楼主不谋而合,我也很期待 Ruby 社区发力 http/2, 不过貌似其他语言框架也很少跟进。 也许大家使用习惯还没发生改变吧 , push 时代更像是 live 时代,场景想不到太多

#1 楼 @small_fish__ 我个人觉得这个不是缺场景的问题,Firebase 的 API 里已经开始做 Real Time 的东西了,在客户端主动去服务器端拉数据之外,服务器也可以把新数据主动推送到客户端。

我的想法是这个和当年的下拉刷新一样,只需要一个引爆点,一旦有一个流行的 app 把这个东西引入,培养出来习惯之后,所有的 PM 都会要求工程师同样去做这些事。这时如果没有解决方案,那不是工程师的锅,但是既然 HTTP/2 给出了这样的架构我们还不去这样做的话,那就是我们的问题了。如果真到了每个 app 都这样做的时代,Ruby 才去应对就晚了

如果是 to PHP 呢? 就开放速度来说和解决方案来说,PHP 也足够成熟。它在真正服务器的性能上比 rails 能强多少?

#3 楼 @pathbox 这里我建议的 metric 不仅仅是 “足够成熟”,而是 “是否可以带来新架构的可能性”,我对 PHP 不熟没法做评论,但是从我接触过的 PHP 工程师的平均水平来看,我深表怀疑。

是不是真的有必要追求 Rails/Ruby 那可能只有 10% 或者 20% 的生产力提升,而抛弃整个框架设计层面的许多可能性。

肯定要参考公司规模和盈利水平了,社区方向是折衷,有金主支持社区的另说了。

#2 楼 @defmacro 确实,怕有些东西,突然就火了

7楼 已删除

这只是一个调度器和 supervisor 在哪里的问题.

http2 push 的问题加个 link rel=preload 头自然就能用上 push 的特性 (nghttpx, h2o 都支持). nginx 系的 cloudflare 也支持这个 (感觉是私有实现, 没开源). 没有 http2 push 这个 link 头也是有意义的.

#8 楼 @fcicq 我理解你是想说 http2 协议自己的 server push 是只能推到 cache 推不到 application 层的,但是还有个东西叫做 Server Sent Events。同时 HTTP2 只是我举的一个例子而已,我的核型观点是 Ruby 圈不务正业好久了

#9 楼 @defmacro 这件事的标准做法还是 websocket. 用 h2 的味道并不对.

后面关于"不务正业"的情况不清楚. 如果只是 ruby 系的方案不如流行的玩意酷从而失去人气的话, 这个事没啥特别的.

#10 楼 @fcicq 很抱歉,说 websocket 比 h2 味道更正确对我来说,跟无数标榜着 xxx is yyy done right 的无聊 library 没什么区别,都是觉得品味重于一切,而没有意识到一个人的品味跟另一个人可能完全不同。

更多的情况下,我不会只关注代码写起来漂不漂亮,我更会关注是否有架构上的可能性,而不是为了一点点 DSL 的好处给架构上增加更多的难度。当然在其他条件相同时,我赞同代码是应该写得漂亮一点,但是话又说回来,漂亮不漂亮怎么衡量呢?

Talk is cheap. Show me the code.

Rails 不单单是语言实现的层面 而是一种开发哲学理念的实现 从这点来说,Rails 与具体语言无关

说 Rails 是理念的,这理念至少落后 5 年了

#15 楼 @nouse 介绍介绍现在是啥理念?

#16 楼 @zgm Rails 就是 web 2.0 时代的产品,你还在写 web 2.0 吗?

#17 楼 @nouse 现在是 web 几点 0 ?现在的理念是啥?

#18 楼 @numbcoder 现在的理念不是很明显吗?现在的明星企业 Uber/Slack/Airbnb 靠什么?

纳闷的是我却时常还会碰到好多 Web 1.0 的网站😈 😥

#19 楼 @nouse Uber/Slack/Airbnb 靠的是什么理念?

#12 楼 @rei 要 code 的话 Elixir 满满都是 code,我只是想引发一个 “为什么 Ruby 社区见不到这样的 code” 的讨论

#13 楼 @huacnlee 这个我赞同,我本人也从 Rails 中学到很多理念,但是我想要表达的一个观点是:在现在这个时代,仅仅靠 Rails 的理念是不够了,Ruby 圈需要更多的空间。

文中的 benchmark 有点问题, 事实上通过 Python/Rails 和通过 SQL 查询的区别达不到 10 倍, 快查询 2 到 3 倍的差别是应该有的, 慢查询大头还是在 SQL

openresty 啊我试过, 感觉啥都干不了... 我是被宠坏了

#22 楼 @defmacro

前两天 Teddy Wang 给我看了他们用 Elixir 写的 api, 生产环境居然有 2ms 的 response time。瞬间毁了我的三观,好快,好快,好快。

学一下 Elixir,扩充一下知识体系挺好。

#19 楼 @nouse 跟什么时候诞生有什么关系? HTML 什么时候诞生的? 你还写吗?

#24 楼 @luikore 这个是小细节好吧。。。我们用 Redis 做后端的服务,同样的逻辑 OpenResty 可以比 Ruby 快到 2 到 3 倍,这里数据库不是瓶颈了。。。况且这里从来没有说 Ruby 搞不定这些事情,这里都只是说用 Ruby,Python 之流可能需要额外花好多精力来处理这些在其他框架里没有的问题

另外你适合花大精力推广 Haskell。。。不适合鼓吹 Rails。。。

#25 楼 @xiaoronglv 现在就是这样,Ruby 拼死拼活优化之后,可能都没有别的技术随便拿来写写的快(当然我不是在暗示这里提到的 Teddy Wang 他们只是随便写写,2ms 还是很牛的,不过随便写写可能也有几十 ms 的级别的了,这基本上跟合理优化过后的 Rails 是一个量级了)

这已经是一个很危险的信号了:如果我们再不反思如何变通,而是继续死心眼的坚持 “瓶颈在 SQL 而不在 Rais”,或者是 “你需要那么快么”,或者是 “机器比人便宜”,那从 Ruby 圈流失的人只会越来越多。

#26 楼 @zgm 很遗憾,html 现在的重要性越来越少了,主流的前端框架都是 virtual-dom 模式,用 State 产生 html。

#29 楼 @nouse 那还不是产生 HTML...

讨论到此结束

#30 楼 @zgm 这个结论太没有意义了,ruby 最后也是生成机器码,activerecord 也是生成 SQL

html 尤其是 DOM 树是非常低效的,看看 atom 的表现就知道了。看到 shadow dom,我觉得眼前一亮,不过这个 shadow 好像还不是 COW 的概念,设想如果 HTML 有 COW,把相同的 DOM 集合在一起,内存也会得到充分利用。

http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/

#28 楼 @defmacro 这有两个问题: Ruby 虚拟机缺少一些优化, ActiveRecord 生成 SQL 的 DSL 没法静态编译

归根还是需要语言上的改进

#32 楼 @luikore 这是一方面,另一方面是基于 Rack 的这套系统也从来没为性能考虑过。参考 OpenResty 里面是可以跑 Lua 官方的实现以及 LuaJIT 的,根据场景的不同,很多重 IO 轻计算的需求中,Lua 官方实现即使就是一个 interpreter,也没有比 LuaJIT 慢很多,归根结底是基于 coroutine 的结构减轻了很多架构上的负担。

所以我赞同 Ruby 本身的语言设计就不适合优化性能,但是 ecosystem 的方向也没有为性能考虑过,假如大家都在 fiber 的方向上努力,那即使达不到 2ms 那种级别的性能,至少也不会是现在赤裸裸的被嘲笑的现实了。所以我觉得总把锅放在虚拟机上面是不对的。

PS:ActiveRecord 真心不熟这个就不直接评论了,省的被抓到小辫子,毕竟吕神歪楼的能力还是一等一的 😈

话说 ruby 到现在还没考虑上 JIT 么。。

#34 楼 @ywjno Matz 表示试过,但是导致了很多 bug 和不稳定,所以决定稳一点

另外可以看看 Introducing Helix 这篇文章,Yehuda Katz 还有一些人开始从 Rust 上找改善性能的突破口了

#28 楼 @defmacro 当微服务架构的时候,开发一些 api, 我从 ruby 切换到 golang ,在不经过任何优化的情况下,性能也非常理想,架构简单很多,根本没有那么多的中间层。

#37 楼 @small_fish__ 是的我们也有同样的体验,从来就不需要那些无聊的 Russian Doll Caching,感觉就是自己给自己找麻烦。

另外就是如同上面 @nouse 说的(虽说我觉得这位同学吵架朝偏了),现在越来越多的 startup 的架构是前段直接 native app,或者是 web app,然后通过基于 JSON 的 API 来跟服务器通信,这样 Rails 提供的很多拼模版的功能完全没有必要了,而且还带来额外的性能负担。从这个角度讲,可以认为 Rails 这一套已经逐渐过时了(是的我了解有 Rails API 的存在,但是性能还是很拙急)

同时 H2 Server Push/Web Socket 带来的 Real Time 架构是 Rails,甚至基于 Rack 的 Ruby 都没有办法处理的。从这里来说,我感觉现在再选择这一套就是先给自己挖了个大坑,然后安慰自己这个坑还不够深。。。

最后再给一刀,虽然我尽一切可能不用 Elixir,但是 Elixir/Phoenix 这一套也已经挤压到传统的 Rails 生存空间了,这是刀刀把人往死路上逼啊

还是那句话,我个人的观点是,虽然现在 Rails 看起来还可以,但是其实已经到了很危险的时刻了,社区再不做些什么,就只能是走向衰落了

#36 楼 @jasl 最近刚刚有 VM 级的大神表示这条路不是很好:https://www.youtube.com/watch?v=b1NTaVQPt1E,我很尊敬 Yehuda 这个人,但是每个人都是有自己擅长的领域的,涉及底层性能优化部分,个人认为 Yehuda 不是很懂。

另外就是跟我之前回复吕神的观点一样:现在问题不仅仅是 VM 层,更多的是这个 ecosystem 导致的架构上没有什么灵活性,而且问题起源甚至不在 Rails,而在 Rack 层。

我对 Rails 了解越多就越不喜欢 Rails 的很多理念,虽然带来了一些书写上的方便,和前期开发效率的高效。比如 ActiveRecord(查询和表示的耦合、callback 等)、Rails 自造的 Autoload、试图自己实现前端的工作等等。感觉因为 Rails 一直都是从 Ruby 分裂的状态,使得整个 Ruby 社区都有点被 Rails 带着(带跑?)的感觉,很多时候其实已经不是在写 Ruby 了,Rails 本身已经是一门语言了

当然,简单的应用还是可以用 Rails 写啦

#39 楼 @defmacro

  1. 对的,我需要过度的关心 cache, 纠结用那种 server, 这根本就是比较蛋疼的事情,中间层越多,架构复杂度就越大。
  2. 我也有相似的感觉,现在很多应用最开始需要的只是 json API,但是 ruby 的 json render 速度确实比较捉急。

#38 楼 @luikore 太长了就不逐条回复了,况且很多观点我是支持的,我只写几点:

  • 我举 Lua 的例子,只是说 VM 的优化是一条可以走的路,但并不仅仅是唯一的路,Ruby 即使只是现在的 VM 不去改动,从 library 的层面也可以做很多优化,但是 Rack 这边已经把路线都绑死了。而且 Ruby 社区的一个坏处是死绑 Rails/Rack 不放手,不像 Python 什么的因为从一开始就是多种 library 并行,你说一个其他的解决方案不像 Ruby 圈里很多人会直接流露出 “烧死异教徒” 的眼神
  • 关于CGI 的历史遗留,这个真的是我遗漏了,我一直以为 hash based API 改成 object based API 更多的只是语法糖的处理,真没想到这个
  • C 扩展的优化部分,同样参考,这个可能也是一个画的很好的大饼,但实际上能达到什么程度不太好说。不过这个不重要,我要表达的观点从来也不是只要改善 VM
  • 是的,HTTP/2 跟 Web Sockets 都不是万能药。但是至少处于竞争关系的语言都有相对应的解决方案,而不是像 Ruby 这样,表示不想跟你说话并扔给你一个 ActionCable 😂 另外 Faye 也不是一个很好的解决方案,我们这边有太多的库为了兼容 Rails 这一套而放弃 Fiber 或是其他的可能性了
  • 从来就没有人说 Fiber,eventmachine,coroutine 这些没有问题,只是当每个人每写一个 Ruby 库都假装 Fiber 这一套不存在,而只关心兼容 Rails 这一套时,问题就出现了。我反复提到 OpenResty,也不是说 OpenResty 就没有毛病,相反 OpenResty 写起代码来很烦,烦到我还保持了 Ruby 这套架构没动,当确认不需要太高的并发时,还用 Ruby 这一套。但是 OpenResty 至少有一点做对了:OpenResty 里基于 coroutine 做了一个完全异步的 socket,这套 socket 同时保持了跟已有的非 OpenResty 的 Lua 库中的 socket 完全相同的 API,这样的结果就是,如果针对这套 API 编程写库,那并不是十分关心下面是在原生的 Lua 以及 POSIX 的 socket 上跑,还是 OpenResty 里面基于 coroutine 的 socket 上跑。这才是我觉得 Ruby 圈里我们应该考虑前进的方向。而不是一味的列举说 coroutine 也有坑也不好,就像上面说的,一切都是 tradeoff,当我想接受 coroutine 的弱点同时拥抱它的优势时,不应该是面对市面上 99% 的 Ruby 库都不兼容的一个悲惨景象

就像我反复提到的,这里不是说 Rails 完全不好,这里更多的是说,我们需要给大家提供更多的 options,不然现在 Ruby 圈的弱点会远远压倒仅剩不多的好处

@luikore 再补充一点,反复提到用 Fiber 的另一个好处是针对合适的项目可以直接上 mruby 了,没有必要搞 CRuby 这一套,配合 nginx 或者 h2o 嵌入使用 mruby 又是新的一片天

huacnlee 将本帖设为了精华贴 07月12日 10:59
46楼 已删除

#43 楼 @defmacro python 也有 wsgi, 和 rack 差不多. 就是框架没这么统一

#47 楼 @luikore 是的,但是对于 python 圈来说,不遵守 wsgi 没像不用 rack 这么满是邪教的感觉,所以情况会好很多

#19 楼 @nouse by the way, airbnb is built on rails.

@nouse 的观点我非常赞同。rails 适合那种服务端渲染 html 的应用,当现在普遍习惯写富前端 app 的时候,rails 在 api 服务器编程方面并没有体现出比 node.js 更多的优势。最好用的就是 activemodel 咯,但慢也慢在它,而且其他语言的 orm 也是存在的嘛。

#49 楼 @joshhu Thanks for the information, it seems they started with Rails 2.3 in 2009, and now they also adopts nodejs in backend. http://www.slideshare.net/spikebrehm/the-evolution-of-airbnbs-frontend/53

感觉如果能把缓存覆盖率做高,gevent 这类并发机制就尽量可以不用了,我们这边有几个 python rpc 服务摘掉 gevent 也可以做到几 ms 的延时几 w qps,与打 gevent 占用的资源差别不大,都挺吃机器的... 这时异步带来的复杂性多于好处,接口的 P95 等延时指标容易躺着受其他请求的 cpu 操作干扰影响诊断问题,设不好协程池子会傻 accept 请求容易过载,数据库池子设大了会打爆连接数设小了又限制并发

PHP 核心开发者 Laruence(鸟哥)在 QCon 2015 上说了这么一段话(大意):

我曾经用了 PHP 和某高级语言做 hello world 的 benchmark ,结果某高级语言胜过 PHP 一个数量级。 然后我分别添加了一条 SQL 查询,它们变成了一个数量级,但是某高级语言还是比 PHP 快两三倍。 然后又加到 10 条 SQL 查询,他们几乎没区别了。

https://www.v2ex.com/t/191046

开发效率对我来说还是有一定优势的。。。。太讨厌 java 的各种配置和下载 jar 包。。。。

貌似现在那边也有 play 和 grails,都没有尝试过。 有 maven,gradle 和各种 jar 解决方案,但是好像资深 java 都不喜欢用。。。。他们还是喜欢到处找 jar,然后一个一个解决 CNE.

#53 楼 @imwildcat 鸟哥这种 php 死忠的话就不要深究了

orm 发展了这么多年就是为了把人从 sql 里面解放出来。建议学习学习 sequel,比如自动生成 prepared statement,http://sequel.jeremyevans.net/rdoc-plugins/classes/Sequel/Plugins/PreparedStatementsSafe.html 还有 rcte 支持,不要手写 common table expressions http://sequel.jeremyevans.net/rdoc-plugins/classes/Sequel/Plugins/RcteTree

用过 openresty ,快,但是稍微复杂点的逻辑写起来就很繁琐了。 从全栈角度看 Rails 优势还是很大,毕竟周边库那么多 非全栈的话每个语言、框架都有各自的优势,没有可比性

phoenix 比 rails 简单直接的一点是可以针对不同的 request route 设置不同的 pipeline, rails 至少应该把 mount middleware 这段生成到 initializer 中去...


再扯扯对 HTTP/2 的一些思考...

其实单连接多请求好处是每个请求的 overhead 减少了, 一些场景已经不需要 sprite 打包图片了 反正 Rails 的 asset pipeline 生成 sprite 和 font 又复杂又有点问题, 那干脆就用 HTTP/2 serve image / svg, 的确是 nginx 换一下就能得到好处...

但如果有很多特别小的图片例如图标, http2 也没有 sprite 性能好, 但为了技术栈简洁起见, 把图标 base64 inline 到 CSS 里更简单.

一个资深 erlang 开发弱弱的问一句,HTTP/2 和 Ruby/Erlang 有毛关系,为何会扯到 Erlang/Ruby 上?

#59 楼 @lilijreey 因为现在 realtime programming 越来越重要了,有了真正意义的 server push。

61楼 已删除

#60 楼 @nouse 如果是重 I/O 的实时应用,Erlang 是不错的选择,也可以说是一个很先进的选择

优秀的产品与需要无关。

首先不好意思挖个坟,如今各种语言各种框架大爆炸,XXX 的 YYY 框架比 Rails 快 ZZZ 倍已然成为日常。XYZ 都是变了而 Rails 总是常量,从侧面可以看出 Rails 之于 Web dev 的特殊地位。

的确 Rails 在面对日新月异的项目/业务需求时常常力不从心,比如 websockets/高并发场景,如果我有一个 realtime 的产品需要处理几十上百万的并发我会毫不犹豫地选择一门 FP 和 tool chain,比如 Elixir, Clojure, etc。

然而这种明显项目毕竟是少数,独角兽一年也出不了几个,我辈 90% 的屌丝开发者在做 90% 的屌丝项目(😅 自黑,请勿对号入座)。面对这些项目我认为大部分项目的需求用 Rails web2.0 那套都足够了。君不见 Basecamp Github 甚至 Shopify 用正统或类似 Turbolinks + SR view + SRJ(Stimulus/Jquery) 那一套,照样可以应付千万级别的用户,X00k 级别的并发,这已然超过 95% 的项目。SPA + SSR + VDOM 对于普通项目的提升能有多大?增加的复杂性和冗余 (NOT DRY) 又有多少?值得吗?这应该是技术选型前最值得考虑的问题。

就像 DHH 和他的小伙伴们用 TL + SRJ + Stimulus 让项目照样稳定运行持续成长 (Desktop IOS Android Mobile Email 一套通吃)。说的世俗一点,DHH 美刀大把赚,还能省出的时间每年几次带着美妻,孩子从冰天雪地的芝加哥到加州 Malibu 的海边豪宅渡假赛车(可以 follow 他的 IG: https://www.instagram.com/dhh79/?hl=en)。

No fancy “COOL KIDS” tech stack, but handy tools for solving real problems, 这不是做事的一个理想状态吗

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册