Ruby光纤调度器

2022-03-01 22:27:42

Fiber Scheduler支持Ruby中的异步编程。该功能是Ruby 3.0的一大新增功能,也是awesome async gem的核心组件之一。最棒的是你没有';我们不需要一个完整的框架来开始!它';使用一个独立的光纤调度器,只需几个内置的Ruby方法,就可以实现异步编程的好处。

语言中内置的一组用于阻止操作的钩子。钩子实现被委托给光纤。调度程序对象。

实现异步行为。这是一个需要程序员显式设置的对象,因为Ruby不提供默认的光纤调度器实现。

非常感谢塞缪尔·威廉姆斯!他';s是一位Ruby核心开发人员,他在语言中设计并实现了光纤调度器功能。

光纤调度器接口是一组用于阻塞操作的挂钩。它允许在发生阻塞操作时插入异步行为。这些挂钩是用Fiber::SchedulerInterface类记录的。

钩子是低级的。这会产生少量的钩子,每个钩子处理许多高级方法的行为。例如,#address_resolve钩子负责处理大约20种方法。

钩子只有在有纤维的情况下才能起作用。调度器对象已设置,挂钩';实现被委托给该对象。

让';让我们来看一个显示如何实现内核#sleep hook的示例。实际上,所有钩子都是用C编写的,但为了清楚起见,这里使用了Ruby伪代码。

如果是纤维。调度程序对象已设置–运行其#内核_sleep方法#内核_sleep应该异步运行sleep。

否则,执行常规的同步_睡眠,将阻止当前线程,直到睡眠完成。

概念";阻塞操作";已经提过好几次了,但这到底是什么意思?阻塞操作是Ruby进程(更具体地说:当前线程)等待的任何操作。阻塞操作的更具描述性的名称是";等待操作";。

作为反例,以下代码段需要一段时间才能完成,但不包含阻塞操作:

如果[0,1],def fibonacci(n)返回n。包括n斐波那契(n-1)+fibonacci(n-2)endfibonacci(100)

获得斐波那契(100)的结果需要很多等待,但它';他只是一个程序员';等着呢!Ruby解释器一直在工作,在后台处理数字。朴素的斐波那契实现不包含阻塞操作。

开发关于阻塞操作是什么(或不是什么)的直觉是有好处的,因为异步编程的全部目的是同时等待多个阻塞操作。

如果想在Ruby中启用异步行为,需要为当前线程设置一个Fiber Scheduler对象。那';光纤已经用完了。设置_调度程序(调度程序)方法。该实现通常是一个定义了所有Fiber::SchedulerInterface方法的类。

Ruby不提供默认的Fiber Scheduler类,也不提供可用于此目的的对象。这似乎很不寻常,但不将光纤调度器实现包含在语言中实际上是一个很好的长期决定。它';最好把这个相对快速发展的问题放在核心Ruby之外。

从头开始编写Fiber Scheduler类是一项复杂的任务,因此它';建议使用现有的解决方案。可在Fibre Scheduler list项目中找到实施列表。

所有示例都使用Ruby 3.1和fiber_scheduler gem中的FiberScheduler类,该类由您自己维护。对于这些示例来说,这个gem并不是一个硬依赖项,因为如果对FiberScheduler的引用被另一个Fiber Scheduler类替换,下面的每个代码段都应该仍然有效。

上面的代码创建了两个光纤,每个光纤发出一个HTTP请求。请求并行运行,整个程序在2秒内完成。

在当前线程中设置启用光纤的光纤调度程序。安排方法工作,光纤异步工作。

该示例仅使用标准的Ruby方法,包括光纤和光纤。设置调度程序和光纤。自Ruby 3.0以来,日程安排一直可用。

要求";光纤调度";要求";httparty";要求";打开uri";要求";redis和#34;要求";续集";DB=续集。博士后续集。扩展(:fiber_concurrency)光纤。设置调度程序(FiberScheduler.new)光纤。计划做URI。开放式(";https://httpbin.org/delay/2 ") 末端纤维。计划不要使用任何HTTP库HTTParty。获得(";https://httpbin.org/delay/2 ") 末端纤维。schedule do#适用于任何TCP协议库Redis。刚出现的blpop(";abc123";2)端光纤。计划进行数据库查询。运行(";选择pg#U睡眠(2)";)末端纤维。安排睡眠2个月。计划执行#运行系统命令'sleep 2'结束

如果我们按顺序运行这个程序,大约需要12秒才能完成。但由于这些操作并行运行,总运行时间仅为2秒多。

你';我们不局限于发出HTTP请求。任何';s内置在Ruby中或由外部gem实现!

在缩放示例中选择了sleep方法,因为它的开销很低。如果我们使用网络请求,执行时间会更长,因为需要建立数千个连接和执行SSL握手等开销。

异步编程的主要好处之一是同时等待许多阻塞操作。随着阻塞操作数量的增加,好处也会增加。幸运的是,它';它非常容易运行大量光纤。

Ruby只需要一个光纤调度器和两个内置方法就可以异步工作——不需要框架!

它';这很容易做到。选择光纤调度器实现,然后使用以下方法:

纤维set_scheduler(调度程序)为当前线程设置光纤调度程序,使阻塞操作表现为异步。

一旦开始运行,就可以通过将任何代码封装在光纤中来实现异步。计划块。

使用这种方法,整个库都可以轻松地转换为异步,而且几乎不需要比这里显示的更大的工作量。

异步编程的最大好处是并行化阻塞/等待操作,以减少程序运行时间。这通常会转化为在单个CPU上运行更多操作,或者更好地使用web服务器处理更多请求。