Rails Ruby 回调机制解释

darren · 2019年10月14日 · 最后由 yfractal 回复于 2019年10月15日 · 4104 次阅读

最近在 ActionCable::Channel::Base.subscribe_to_channel 函数中看到

def subscribe_to_channel
  run_callbacks :subscribe do
    subscribed
  end

  reject_subscription if subscription_rejected?
  ensure_confirmation_sent
end

然后查看了https://baike.baidu.com/item/%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0/7545973?fr=aladdin 百度的详细解释,回调函数就是一定条件触发的函数,之前听过介绍 nodejs 的回调机制,nodejs 的回调机制可以让 node 处理高并发而不占用大量资源 (道听途说没有验证),有没有关于 ruby 的回调详细解释?是否 ruby 和 js 都是单线程的,是否可以通过回调机制避免一些阻塞的操作,典型的比如文件读写?和其他语言在实现上有什么区别?这一块不是很懂,各位大佬有没有推荐的资料😀

  1. run_callbacks 是 ActiveSupport::Callback 提供的方法
  2. Ruby 不是单线程,避免阻塞这个话题太大,可以看一下 nio4r,action cable 也有用到
piecehealth 回复

我现在好奇的是要使用回调避免阻塞,其前提应该是需要使用多线程,否则无论如何在单线程上一定会阻塞的,关于 ruby 的线程,其实也是越学越糊涂, 1.最早是看<松本行弘的编程世界>和 matz 自己提到过 ruby 最后悔的是线程的设计,因为他使得语言变得复杂,而且他说线程这个功能是后来匆忙加上去的,对于是否单线程,matz 本人好像没有说,但是我猜测是单线程的。

  1. 我帮别人做过一个项目,在做 amazon 的云存储时,文档明确介绍的是如果使用 js 或者 ruby 这样的语言读取文件的时候,是会阻塞应用程序的. 3.另外还有文章说,ruby 的县城取决于操作系统和编译器 https://cloud.tencent.com/developer/ask/51206 如这篇文章所述. 所以各个说法都不一样,而目前又没有不太会读 ruby 的源码,所以一直都比较困惑,如你所述如果 ruby 不是单线程,那么可以怎么证明?

你先证明 Ruby 是单线程😈

早期 Ruby 线程是很弱语言级别的线程 (绿色线程),但是很早之前已经换成系统线程了。

看来要看源码了,这个点越学越糊涂😂

ruby 和 js 回调完全是两个东西。js 是异步回调。。。ruby 的回调更像是 hook

把 ruby 和 rails 分开看会好一些

毕竟线程模型不同。ruby 可以通过 gem 扩展出和 nodejs 类似的异步回调

是否可以通过回调机制避免一些阻塞的操作,典型的比如文件读写?

这个要看是否有基于异步的文件读写操作。ruby 本身没异步。。。(别和我提 ruby 的绿色线程,这东西可以当作没有

看一下 wisper 这个 gem

node.js 整个运行环境是基于事件驱动的,内部不断的执行事件循环,回调是异步执行的。

Ruby 的基本环境是顺序执行,除非显式的调用线程/进程和未来的 guilds。ActiveSupport 只是提供一种回调语法,本身还是顺序执行。

要像 node.js 那样实现基于事件驱动的异步,可以看 https://github.com/eventmachine/eventmachine ,并且所有用到的库都需要基于事件模型(在 Ruby 世界不流行)。

事件驱动对于重 I/O 的场景很适用,例如 nginx,代理服务器大部分工作是转发请求,适合用事件驱动。如果重 CPU 的场景使用事件驱动,可能上下文切换的支出反而导致效率降低。

另外 Ruby 的多线程已经可以在 I/O 阻塞的时候,切到另一线程执行,增加 CPU 利用率和提高并发量。

Threads (in Ruby): Enough Already https://yehudakatz.com/2010/08/14/threads-in-ruby-enough-already/ 这篇文章写在 2010 年,里面提到的一些问题已经解决很久了。

未来的 Guilds 希望可以增加单进程利用多核 CPU 的能力。

lithium4010 回复

👍 这个包好,看了一下源码,它用线程实现异步,这个对我帮助很大

a-wing 回复

对,就是日常写两个语言感觉不太一样,很想研究一下他们的线程模型

Rei 回复

原来原理如此,这个文章非常干货,回答了很多工作中遇到的问题👍

nodejs 的回调机制可以让 node 处理高并发而不占用大量资源

不是回调机制,是异步 I/O 机制。Ruby 也有回调机制,和 node 是类似。node 单线程,ruby 全局锁。因为要 thread safe(避免一段代码被两个线程同时执行)。

ActionCable,用一个线程跑了一个 event loop,ActionCable 里的 ws 操作,都是异步 I/O 操作。用 select 监听。ready 了调用对应的 callback(异步 io 使用 nio4r 做的)。

理论上,性能(实际上似乎不是?没压过)应该和 nodejs 差不多。

不过 midori https://github.com/midori-rb/midori.rb 的实现方式和 AnyCable 差不多,性能就和 nodejs 就几乎一样。

Ruby 不是单线程,但是有全局锁。

多线程可以很大程度解决 I/O 问题。但线程开销太大,如果需要更好的性能的话,还是需要绿色线程来做。

最后,夹带点私货,线程和 nio 的比较,可以看看这个 https://ruby-china.org/topics/38404 (写的不怎么样,可以将就看看。。。)

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