12
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

このコードは同期スタイルで動作します。最初のリクエスト、2 番目、3 番目。すべてのリクエストを非同期で送信し、すべてが完了したら印刷したいと思いますurls

それを行う最良の方法は何ですか?ファイバーはそれに適していますか?

4

8 に答える 8

16

ちょうど 1 年と少し後にこれを見ましたが、Google 社員にとっては手遅れではないことを願っています...

Typhoeusは、これに対する最良の解決策です。libcurl を非常にエレガントな方法でラップします。max_concurrency窒息することなく、最大約200まで設定できます。

タイムアウトに関しては、Typhoeus に:timeoutフラグを渡すと、応答としてタイムアウトが登録されます。必要に応じて、要求を別のヒドラに戻して再試行することもできます。

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
于 2015-01-05T01:54:28.960 に答える
15

スレッドを使用した例を次に示します。

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
于 2010-01-24T21:08:18.927 に答える
1

これは、C ライブラリcURLで実行できます。そのライブラリのruby​​ バインディングは存在しますが、そのままではこの機能をサポートしていないようです。ただし、それを追加/修正するパッチがあるようです (サンプルコードはページで入手できます)。これは良くないように思えますが、他に良い提案がない場合は試してみる価値があるかもしれません。

于 2010-01-24T20:12:55.653 に答える
0

work_queue gem は、アプリケーションでタスクを非同期かつ並行して実行する最も簡単な方法です。

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
于 2015-06-19T19:12:44.717 に答える
0

Net::HTTP.get のそれぞれを別のスレッドで実行することができます。そして、すべてのスレッドが終了するのを待ちます。

ところで、URL を印刷すると、リンクとコンテンツの両方が印刷されます。

于 2010-01-24T20:24:06.033 に答える
0

その後、関数の後に何をしたいかによって異なります。シンプルなスレッドでそれを行うことができます:

参照: http://snipplr.com/view/3966/simple-example-of-threading-in-ruby/

于 2010-01-24T20:18:00.703 に答える