惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
Check Point Blog
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
Secure Thoughts
Recorded Future
Recorded Future
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
The Blog of Author Tim Ferriss
B
Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Google DeepMind News
Google DeepMind News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
A
Arctic Wolf
T
The Exploit Database - CXSecurity.com
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
AWS News Blog
AWS News Blog
MongoDB | Blog
MongoDB | Blog
Y
Y Combinator Blog
Google Online Security Blog
Google Online Security Blog
T
Troy Hunt's Blog
I
InfoQ
L
LINUX DO - 热门话题
WordPress大学
WordPress大学
C
Cisco Blogs
G
GRAHAM CLULEY
The Register - Security
The Register - Security
A
About on SuperTechFans
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Schneier on Security
Schneier on Security
Project Zero
Project Zero
H
Hackread – Cybersecurity News, Data Breaches, AI and More
P
Privacy & Cybersecurity Law Blog
Cloudbric
Cloudbric
H
Hacker News: Front Page
小众软件
小众软件
雷峰网
雷峰网
The Hacker News
The Hacker News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
Tor Project blog
博客园 - 聂微东
N
Netflix TechBlog - Medium
V
Vulnerabilities – Threatpost
The GitHub Blog
The GitHub Blog
腾讯CDC
P
Palo Alto Networks Blog
Scott Helme
Scott Helme

Ruby

一個用 DIDComm 實現服務器間通信的 Rails demo - V2EX RubyConf China 2024 参会报告 - Day 1 - V2EX 有对 Ruby 感兴趣的吗? - V2EX MRuby Devkit 一个简单的脚手架,帮助你像 Go 一样把 Ruby 编译成可执行二进制文件 - V2EX 使用 Ruby-build 在 MacOS 上 编译 Portable Ruby - V2EX [翻译] Async Ruby(异步 Ruby) - V2EX Ruby 3.2.0 发布 - V2EX Ruby on Mac - V2EX 用 100 行 Ruby 代码模拟 JavaScript 的 Eventloop - V2EX 管窥蠡测从思考游戏到实现 2048 - V2EX 用 Ruby 讲从创业到 996 公司的故事(戏说 master-worker 模式) - V2EX Sinatra 源码分析 (一):set 系统工作原理 - V2EX 《Ruby 设计模式》笔记 - V2EX Ruby 标准库有趣部分摘要 - V2EX 并行并发进程线程协程 GIL 概念简明解释笔记(Ruby 举例) - V2EX Sinatra 的 app 模板,提供一些胶水代码支持类似 Rails 的体验 - V2EX Ruby 的方法查找再往前一步 - V2EX 有在深圳至简天成的吗? 求加微信 - V2EX Ruby 3.0.0 Released - V2EX 新建了个 ruby 中文讨论群 - V2EX Language Hopping, Ruby 为什么不火,一点瞎想 - V2EX ruby,一代优秀语言就这样陨落了吗? - V2EX ruby 的 "a" 和 :a 能转换吗 - V2EX 求大佬帮安装一个 mastodon,有偿! - V2EX notepad++ ssh 一些个小坑 - V2EX 有什么好的方法/IDE 阅读 Gem 库的源码? - V2EX 问一个 ruby 的问题 - V2EX 用 discourse 搭了个论坛 求测试 - V2EX 找小伙伴一起开发和完善一个 Ruby 增量代码覆盖率统计工具 - V2EX 都在说抑郁,我们学一下 ruby 吧,一门让你快乐的语言 - V2EX ruby2.6 的 jit 大家感觉怎么样? - V2EX 在 one-liner 文本处理方面, ruby 比 perl 要逊色吗? - V2EX 使用 ruby 写了一个周报系统 - V2EX ruby 的 devkit 安装 - V2EX 总听人说 ruby 代码写起来很爽,有多爽?怎么个爽法? - V2EX RubyGems 注册不了的? - V2EX Ruby 破环方法为什么比非破坏方法慢一些? - V2EX Ruby Conference 2017 AU - V2EX ruby 这么优雅的语言,怎么没有像 python 这样流行开来? - V2EX Ruby 中 Singleton 方法的另一种理解方式 - V2EX 需要学习 ruby,想问现在 ruby 的主流版本是多少? - V2EX Ruby 的内存占用极限? Ruby 写了一个命令行火车票查看器 - V2EX 有谁用过 Ruby 写的比特币交易平台 Peatio,admin 面板进不去,求教啊啊啊啊啊啊啊 - V2EX 和隔壁的 python 比起来,这节点好冷清 阿里云 OSS Ruby SDK 开发手记 - V2EX 淘宝 RubyGems 镜像有段时间没同步了 - V2EX 为什么 Ruby 给人一种「只有 Rails」的印象?
[翻译] Ruby Fiber Scheduler - V2EX
Mark24 · 2023-10-12 · via Ruby

Fiber Scheduler(纤程调度器)在 Ruby 中实现异步编程。该功能是 Ruby 3.0 的一大增强功能,并且也是优秀的 async gem 的核心组件之一。 最棒的一点是,你并不需要一个完整的框架就能开始!只需使用一对内置的 Ruby 方法,就能独立地实现纤程调度器并享受到异步编程的好处。

纤程调度器主要包括两部分:

  • Fiber Scheduler interface (纤程调度器接口) 这是一套内置于编程语言中的阻塞操作钩子。钩子实现被委托给 Fiber.scheduler 对象。

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

非常感谢 Samuel Williams !他是 Ruby 的核心开发者,设计并实现了纤程调度器这一功能并整合到了语言中。

Fiber Scheduler interface (纤程调度器接口)

Fiber Scheduler (纤程调度器)接口是一套阻塞操作的钩子,它允许在阻塞操作发生时插入异步行为。它像是带有反转的回调:当异步回调被执行时,主阻塞方法不会运行。 这些钩子在 Fiber::SchedulerInterface 类中有文档记录。这个 Ruby 功能背后的一些主要思想包括:

  • 钩子是低层级的。这导致了少量的钩子,每个钩子处理许多高层级方法的行为。例如,#address_resolve 钩子负责处理大约 20 个方法。
  • 钩子只在 Fiber.scheduler 对象设置后才会工作,钩子的实现被委托给该对象。
  • 钩子的行为应该是异步的。

Hook implementation (钩子实现)

让我们看一个示例,显示如何实现 Kernel#sleep 钩子。在实践中,所有的钩子都是用 C 语言编写的,但为了清晰起见,这里使用了 Ruby 伪代码。

module Kernel
  def sleep(duration = nil)
    if Fiber.scheduler
      Fiber.scheduler.kernel_sleep(duration)
    else
      synchronous_sleep(duration)
    end
  end
end

以上代码的阅读方式如下:

  • 如果设置了 Fiber.scheduler 对象 - 运行其 #kernel_sleep 方法。#kernel_sleep 应该异步运行 sleep
  • 否则,执行常规的 synchronous_sleep,它会阻塞当前线程直到 sleep 完成。

其他的钩子的工作方式也类似。

Blocking operations (阻塞操作)

已经多次提到了"Blocking operations (阻塞操作)"这个概念,但它到底是什么意思呢?阻塞操作是指任何 Ruby 进程(更具体地说:当前线程)最终会等待的操作。一个更具描述性的名称是“waiting operations (等待操作)”。 一些例子如下:

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

def fibonacci(n)
  return n if [0, 1].include? n

  fibonacci(n - 1) + fibonacci(n - 2)
end

fibonacci(100)

获取 fibonacci(100) 的结果需要等待很长时间,但只有程序员在等待!整个时间 Ruby 解释器都在工作,后台进行计算。一个简单的斐波那契实现并不包含阻塞操作。

发展对阻塞操作是什么(和不是什么)的直觉是值得的,因为异步编程的整个目标就是同时等待多个阻塞操作

Fiber Scheduler implementation (纤程调度器实现)

纤程调度器实现是 Fiber Scheduler 功能的第二大部分。

如果你想在 Ruby 中启用异步行为,你需要为当前线程设置一个 Fiber Scheduler 对象。这是通过 Fiber.set_scheduler(scheduler) 方法完成的。实现通常是一个定义了所有 Fiber::SchedulerInterface 方法的类。

Ruby 不提供默认的 Fiber Scheduler 类,也没有可以用于此目的的对象。这看起来不寻常,但实际上不将 Fiber Scheduler 实现包含在语言中是一个好的长期决定。最好将这种相对快速演变的关注点留在 Ruby 核心之外。 从头开始编写 Fiber Scheduler 类是一项复杂的任务,所以最好使用现有的解决方案。实现的列表,它们的主要区别和推荐可以在 Fiber Scheduler List 项目中找到。

举个例子

让我们来看看仅使用 Fiber Scheduler 可以做什么。 所有示例都使用 Ruby 3.1 和来自 fiber_scheduler gem 的 FiberScheduler 类,这个 gem 由我维护。这个 gem 对于示例来说不是一个硬性依赖项,因为如果将以下代码片段中的 FiberScheduler 替换为另一个 Fiber Scheduler 类,每个代码片段仍然应该可以工作。

基本示例

这里有一个简单的示例:

require "fiber_scheduler"
require "open-uri"

Fiber.set_scheduler(FiberScheduler.new)

Fiber.schedule do
  URI.open("https://httpbin.org/delay/2")
end

Fiber.schedule do
  URI.open("https://httpbin.org/delay/2")
end

上面的代码创建了两个纤程,每个纤程都进行一次 HTTP 请求。这些请求并行运行,整个程序在 2 秒内完成。

  • Fiber.set_scheduler(FiberScheduler.new) 在当前线程中设置一个 Fiber Scheduler,这使得 Fiber.schedule 方法可以工作,且 fiber 可以异步行为。

  • Fiber.schedule { ... } 这是一个内置的 Ruby 方法,用于启动新的异步 fiber 。

这个示例仅使用了标准的 Ruby 方法 - Fiber.set_schedulerFiber.schedule 自 Ruby 3.0 版本以来就一直可用。

高级例子

我们来看看运行多种不同操作是什么样子的:

require "fiber_scheduler"
require "httparty"
require "open-uri"
require "redis"
require "sequel"

DB = Sequel.postgres
Sequel.extension(:fiber_concurrency)

Fiber.set_scheduler(FiberScheduler.new)

Fiber.schedule do
  URI.open("https://httpbin.org/delay/2")
end

Fiber.schedule do
  # Use any HTTP library
  HTTParty.get("https://httpbin.org/delay/2")
end

Fiber.schedule do
  # Works with any TCP protocol library
  Redis.new.blpop("abc123", 2)
end

Fiber.schedule do
  # Make database queries
  DB.run("SELECT pg_sleep(2)")
end

Fiber.schedule do
  sleep 2
end

Fiber.schedule do
  # Run system commands
  `sleep 2`
end

如果我们顺序运行这个程序,它大约需要 12 秒才能完成。但是由于这些操作是并行运行的,所以总的运行时间仅仅超过 2 秒。 你并不仅限于发起 HTTP 请求。任何内置在 Ruby 中或由外部 gem 实现的阻塞操作都可以工作!

扩展示例

这是一个简单的,显然是人为刻意的示例,同时运行一万个操作。

require "fiber_scheduler"

Fiber.set_scheduler(FiberScheduler.new)

10_000.times do
  Fiber.schedule do
    sleep 2
  end
end

上述代码的完成时间略超过 2 秒。

由于其低开销,sleep 方法被选择用于扩展示例。如果我们使用网络请求,由于需要建立数千个连接并进行 SSL 握手等,执行时间将会更长。

异步编程的主要优势之一是能够同时等待许多阻塞操作。阻塞操作数量的增加将增加这种优势。幸运的是,运行大量协程(fibers)非常简单。

结论

Ruby 只需要一个纤程调度器( Fiber Scheduler )和一些内置方法就可以异步工作 - 不需要任何框架!

使其工作很容易。选择一个纤程调度器( Fiber Scheduler )实现,然后使用以下这些方法:

  • Fiber.set_scheduler(scheduler)为当前线程设置一个纤程调度器( Fiber Scheduler ),使阻塞操作能够异步执行。
  • Fiber.schedule { ... } 启动一个新的纤程,该纤程与其他纤程并发运行。

一旦你开始运行,你可以通过将它包装在一个 Fiber.schedule 块中来使任何代码异步化

Fiber.schedule do
  SynchronousCode.run
end

整个库可以轻松地使用这种方法转换为异步,而且往往不需要比这里展示的更多努力。

异步编程的重大好处是并行化阻塞/等待操作以减少程序运行时间。这通常意味着在单个 CPU 上运行更多的操作,或者更好地,在你的 Web 服务器上处理更多的请求。

祝你使用纤程调度器( Fiber Scheduler )愉快!

Happy hacking with Fiber Scheduler!