Потоки HTTP-запросов в Crystal
У меня есть код, который должен работать "параллельно" (не реально, я знаю, что Crystal не поддерживает параллелизм).
require "http/client"
thread_count = 4
resps = [] of HTTP::Client::Response
mutex = Thread::Mutex.new
urls = [] of String
(1..10).each { |i| urls << "http://httpbin.org/delay#{i}"}
threads = Array.new(thread_count) {
Thread.new do
while url = mutex.synchronize { urls.pop? }
resp = HTTP::Client.get(url)
mutex.synchronize { resps << resp }
end
end
}
threads.map(&.join)
Исходный файл для Thread
класс говорит не использовать его. Во всяком случае, этот код не работает с HTTP::Client
,
1 ответ
Решение
Использование spawn
:
require "http/client"
require "json"
WORKER_COUNT = 4
to_fetch = Channel(String?).new(WORKER_COUNT)
responses = Channel(HTTP::Client::Response?).new(WORKER_COUNT)
WORKER_COUNT.times do
spawn do
loop do
url = to_fetch.receive
responses.send url ? HTTP::Client.get(url) : nil
break unless url
end
end
end
spawn do
10.times do |i|
to_fetch.send "http://httpbin.org/delay/#{i}"
end
WORKER_COUNT.times do
to_fetch.send nil
end
end
start = Time.now
worker_done_count = 0
loop do
response = responses.receive
if response
puts "#{Time.now - start}: fetched #{JSON.parse(response.body)["url"]}"
else
worker_done_count += 1
break if worker_done_count == WORKER_COUNT
end
end