Ruby 是否支持没有第三方库的非阻塞 HTTP 请求?
Does Ruby support nonblocking HTTP requests without a third-party library?
我正在编写 API 来访问我的一台服务器上的资源。 API 的一部分将发出 HTTP 请求。以良好软件设计的名义,我不希望我的 API 被阻塞。
我是 Ruby 的新手,但在 Java 中,我会提供一个异步 API 响应的 returns 期货。在 JavaScript 中,我会在我的方法中进行回调。
我搜索了其他 Stack Overflow 问题,https://github.com/eventmachine/em-http-request 似乎符合我的要求。但是,我对依赖第三方库犹豫不决。是否有 Ruby 原生方法解决此问题,还是大多数开发人员依赖第三方库?
根据我的测试,MRI 仅通过使用线程即可支持非阻塞 HTTP 请求。由于 GIL,线程并不总是允许 Ruby 中的并行性,但 net/http
似乎是例外之一:
require 'net/http'
require 'benchmark'
uri = URI('
n = 10
Benchmark.bm do |b|
b.report { n.times { Net::HTTP.get(uri) } }
b.report { threads = Array.new(n) { Thread.new { Net::HTTP.get(uri) } }; threads.each(&:join) }
end
# user system total real
# 0.010000 0.010000 0.020000 ( 0.102024)
# 0.020000 0.010000 0.030000 ( 0.025904)
自 Ruby 3.0 起,标准库也与 Fibers 和 Async 兼容 gem 因此您可以执行以下操作:
require 'async'
require 'benchmark'
require 'open-uri'
require 'httparty'
n = 3
Benchmark.bm(20) do |b|
b.report "Sequential" do
n.times do |i|
HTTParty.get("https://httpbin.org/delay/1.6")
end
end
b.report "Threads + HTTParty" do
threads = Array.new(n) { |i|
Thread.new {
HTTParty.get("https://httpbin.org/delay/1.6")
}
}
threads.each(&:join)
end
b.report "Async + HTTParty" do
Async do |task|
n.times do |i|
task.async do
HTTParty.get("https://httpbin.org/delay/1.6")
end
end
end
end
b.report "Async + open-uri" do
Async do |task|
n.times do |i|
task.async do
URI.open("https://httpbin.org/delay/1.6")
end
end
end
end
end
我正在编写 API 来访问我的一台服务器上的资源。 API 的一部分将发出 HTTP 请求。以良好软件设计的名义,我不希望我的 API 被阻塞。
我是 Ruby 的新手,但在 Java 中,我会提供一个异步 API 响应的 returns 期货。在 JavaScript 中,我会在我的方法中进行回调。
我搜索了其他 Stack Overflow 问题,https://github.com/eventmachine/em-http-request 似乎符合我的要求。但是,我对依赖第三方库犹豫不决。是否有 Ruby 原生方法解决此问题,还是大多数开发人员依赖第三方库?
根据我的测试,MRI 仅通过使用线程即可支持非阻塞 HTTP 请求。由于 GIL,线程并不总是允许 Ruby 中的并行性,但 net/http
似乎是例外之一:
require 'net/http'
require 'benchmark'
uri = URI('
n = 10
Benchmark.bm do |b|
b.report { n.times { Net::HTTP.get(uri) } }
b.report { threads = Array.new(n) { Thread.new { Net::HTTP.get(uri) } }; threads.each(&:join) }
end
# user system total real
# 0.010000 0.010000 0.020000 ( 0.102024)
# 0.020000 0.010000 0.030000 ( 0.025904)
自 Ruby 3.0 起,标准库也与 Fibers 和 Async 兼容 gem 因此您可以执行以下操作:
require 'async'
require 'benchmark'
require 'open-uri'
require 'httparty'
n = 3
Benchmark.bm(20) do |b|
b.report "Sequential" do
n.times do |i|
HTTParty.get("https://httpbin.org/delay/1.6")
end
end
b.report "Threads + HTTParty" do
threads = Array.new(n) { |i|
Thread.new {
HTTParty.get("https://httpbin.org/delay/1.6")
}
}
threads.each(&:join)
end
b.report "Async + HTTParty" do
Async do |task|
n.times do |i|
task.async do
HTTParty.get("https://httpbin.org/delay/1.6")
end
end
end
end
b.report "Async + open-uri" do
Async do |task|
n.times do |i|
task.async do
URI.open("https://httpbin.org/delay/1.6")
end
end
end
end
end