2010-01-24 3 views
8
require 'net/http' 

urls = [ 
    {'link' => 'http://www.google.com/'}, 
    {'link' => 'http://www.yandex.ru/'}, 
    {'link' => 'http://www.baidu.com/'} 
] 

urls.each do |u| 
    u['content'] = Net::HTTP.get(URI.parse(u['link'])) 
end 

print urls

이 코드는 동기식 스타일로 작동합니다. 첫 번째 요청, 두 번째, 세 번째. 모든 요청이 비동기 적으로 보내지면 모두 urls을 인쇄하고 싶습니다.여러 HTTP 요청을 비동기 적으로 만들기

가장 좋은 방법은 무엇입니까? 섬유는 그 용도에 적합합니까?

답변

1

이 작업은 C 라이브러리 cURL을 사용하여 수행 할 수 있습니다. 해당 라이브러리에 대한 ruby binding이 있지만이 기능을 즉시 지원하지는 않습니다. 그러나, 추가/수정이 a patch 인 것 같습니다 (예제 코드는 페이지에서 사용 가능합니다). 나는 이것이 훌륭한 것처럼 들리지 않는다는 것을 안다. 그러나 더 좋은 제안이 없다면 시도할만한 가치가있을 것이다.

0

당신은 다른 스레드가 인터넷 :: HTTP.get 각각 실행 가질 수있다. 그리고 모든 스레드가 끝날 때까지 기다리십시오.

BTW 인쇄 URL은 링크와 콘텐츠를 모두 인쇄합니다.

12

다음은 스레드를 사용한 예입니다.

require 'net/http' 

urls = [ 
    {'link' => 'http://www.google.com/'}, 
    {'link' => 'http://www.yandex.ru/'}, 
    {'link' => 'http://www.baidu.com/'} 
] 

urls.each do |u| 
    Thread.new do 
    u['content'] = Net::HTTP.get(URI.parse(u['link'])) 
    puts "Successfully requested #{u['link']}" 

    if urls.all? {|u| u.has_key?("content") } 
     puts "Fetched all urls!" 
     exit 
    end 
    end 
end 

sleep 
+0

이 보인다. 그러나 15 초 후에 서버가 응답하지 않으면 스레드를 죽이는 방법은 무엇입니까? – NVI

+1

'Timeout.timeotu (20) do .... end'를 사용할 수 있습니다. 그 러면 오류가 발생하기 때문에 프로그램의 흐름을 따라 뭔가를해야하고'content' 키가 있는지 확인하는 것 이외의 요청이 완료되었음을 태그하는 방법이 있어야합니다. –

+0

Ruby의 Net :: HTTP는 threadsafe입니까? – Daniel777

11

난 그냥 일년 잠시 후 이것을보고 있지만, 이것에 대한 희망을 갖고 너무 늦게 일부 Google 직원에 대한 ...

Typhoeus 지금까지 최고의 솔루션입니다. libcurl을 매우 우아하게 감 쌉니다. 질식하지 않고 max_concurrency을 약 200까지 설정할 수 있습니다. 당신이 :timeout 플래그 Typhoeus 전달하면

은 시간 제한과 관련하여, 그것은 바로 응답으로 타임 아웃을 등록합니다 ... 그리고 당신도 당신이 좋아하는 경우에 다시 시도하기 위해 다른 히드라에서 다시 요청을 넣을 수 있습니다.

다음은 Typhoeus로 다시 작성된 프로그램입니다. 다행히도이 페이지를 나중에 방문하는 사람에게 도움이되기를 바랍니다.

require 'typhoeus' 

urls = [ 
    'http://www.google.com/', 
    'http://www.yandex.ru/', 
    'http://www.baidu.com/' 
] 

hydra = Typhoeus::Hydra.new 

successes = 0 

urls.each do |url| 
    request = Typhoeus::Request.new(url, timeout: 15000) 
    request.on_complete do |response| 
     if response.success? 
      puts "Successfully requested " + url 
      successes += 1 
     else 
      puts "Failed to get " + url 
     end 
    end 
    hydra.queue(request) 
end 

hydra.run 

puts "Fetched all urls!" if successes == urls.length 
0

work_queue 보석은 응용 프로그램에서 비동기 적으로 동시에 작업을 수행 할 수있는 가장 쉬운 방법입니다. 1) 모든 스레드 참조를 추적 :하지만 몇 가지 주요 차이점 -

wq = WorkQueue.new 2 # Limit the maximum number of simultaneous worker threads 

urls.each do |url| 
    wq.enqueue_b do 
    response = Net::HTTP.get_response(url) 
    # use the response 
    end 
end 

wq.join # All requests are complete after this 
1

내가 게시 한 8 월 다소 유사한 답을 포함하고이 주제에 대한 심도있는 블로그 게시물을 작성했습니다 "thread"배열. 2) "join"메서드를 사용하여 프로그램 끝에서 스레드를 묶습니다.

require 'net/http' 

# create an array of sites we wish to visit concurrently. 
urls = ['link1','link2','link3'] 
# Create an array to keep track of threads. 
threads = [] 

urls.each do |u| 
    # spawn a new thread for each url 
    threads << Thread.new do 
    Net::HTTP.get(URI.parse(u)) 
    # DO SOMETHING WITH URL CONTENTS HERE 
    # ... 
    puts "Request Complete: #{u}\n" 
    end 
end 

# wait for threads to finish before ending program. 
threads.each { |t| t.join } 

puts "All Done!" 

전체 튜토리얼 (일부 성능 정보는) 여기로 볼 수 있습니다 : 작동처럼 https://zachalam.com/performing-multiple-http-requests-asynchronously-in-ruby/