2011-01-28 3 views
0

다음은 내가 달성하고자하는 작업입니다. 데이터베이스에 저장된 URL이 10 만개라고 가정하고 각각에 대해 http 상태를 확인하고 그 상태를 저장하려고합니다. 비교적 적은 시간에 동시에이 작업을 수행 할 수 있기를 원합니다.데이터베이스에있는 여러 개의 URL에 대해 동시에 상태 (즉, 200,301,404)의 URL을 확인하는 가장 좋은 방법입니다.

이 작업을 수행하는 가장 좋은 방법이 무엇인지 궁금합니다. 나는 근로자/소비자 또는 일종의 이벤트 모델을 사용하여 일종의 대기열을 사용하는 것에 대해 생각했지만이 시나리오에서 어떤 것이 가장 효과적인지 알 수있는 충분한 경험이 없습니다.

아이디어가 있으십니까?

답변

4

매우 유용한 Typhoeus and Hydra 콤보를 살펴보십시오. 이 두 가지 기능을 사용하면 여러 URL을 동시에 처리하는 것이 매우 쉽습니다.

"Times"예제는 신속하게 작동시켜야합니다. on_complete 블록에서 상태를 DB에 쓰도록 코드를 입력하십시오. 스레드를 사용하여 대기열에있는 요청을 건전한 수준으로 작성 및 유지 관리하거나, 설정된 번호를 대기열에 넣고 완료까지 실행 한 다음 다른 그룹을 반복 할 수 있습니다. 그것은 당신에게 달려 있습니다.

Paul Dix, 원저자 talked about his design goals 자신의 블로그에 있습니다.

이것은 로컬 검색을 수행 할 수 있도록 보관 된 메일 목록을 다운로드하기 위해 작성한 샘플 코드입니다. 20 아래에 11메가바이트 총 76 개 파일로 뽑아 프로 내 몇 살 맥북의 코드를 실행

#!/usr/bin/env ruby 

require 'nokogiri' 
require 'addressable/uri' 
require 'typhoeus' 

BASE_URL = '' 

url = Addressable::URI.parse(BASE_URL) 
resp = Typhoeus::Request.get(url.to_s) 
doc = Nokogiri::HTML(resp.body) 

hydra = Typhoeus::Hydra.new(:max_concurrency => 10) 
doc.css('a').map{ |n| n['href'] }.select{ |href| href[/\.gz$/] }.each do |gzip| 
    gzip_url = url.join(gzip) 
    request = Typhoeus::Request.new(gzip_url.to_s) 

    request.on_complete do |resp| 
    gzip_filename = resp.request.url.split('/').last 
    puts "writing #{gzip_filename}" 
    File.open("gz/#{gzip_filename}", 'w') do |fo| 
     fo.write resp.body 
    end 
    end 
    puts "queuing #{ gzip }" 
    hydra.queue(request) 
end 

hydra.run 

: 나는 의도적으로 사람들이 코드를 실행하기 시작하면 DOS 공격에 사이트를 쓰는에서 유지하기 위해 URL을 제거 초, 무선을 통해 DSL. HEAD 요청을 처리하는 경우 처리량이 향상됩니다. 더 많은 동시 세션을 사용하면 속도가 느려지고 불필요하게 리소스를 사용해야하는 시점이 있기 때문에 동시성 설정을 망쳐 놓을 수 있습니다.

10 점 만점에 8 점을줍니다. 그것은 위대한 비트를 가지고 있고 그것에 춤을 출 수 있습니다.


편집 :

당신은 HEAD 요청, 또는 If-Modified-Since와 GET을 사용할 수 있습니다 제거 URL을 검사합니다. URL의 최신 성을 결정하는 데 사용할 수있는 응답을 제공 할 수 있습니다.

+0

감사합니다. Tin Man, 나는 100 개의 HEAD 요청을 작성하고 동시에 해제하기 위해'EM :: MultiRequest'를 사용하여 em-http로 시작했습니다. 모든 것이 잘 진행되면 약 3-7 (데이터베이스 쓰기 전) 초 내에 완료됩니다. 유일한 문제는 URL 중 하나가 시간 초과 될 경우 60 초를 기다리는 것입니다. 즉, 다음 일괄 처리는 완료 될 때까지 실행되지 않습니다 (모든 일괄 처리에 하나가있는 경우 최악의 경우). 하나의 요청이 다른 요청에 영향을 미치지 않도록이 값을 변경하려고합니다. Typhoeus를 확인하고 그 차이점을 확인하겠습니다. 감사! – MAP

+0

몇 년 전 필자가 쓴 몇 가지 Perl 코드에서 같은 문제가 발생했다. HTTP 타임 아웃을 설정하면 많은 도움이됩니다. 요청 시간이 초과되면 "다음 확인 시간"타임 스탬프를 나중에 적절한 시간으로 업데이트하여 곧 재 시도 될 수 있지만 즉시 적용되지는 않습니다. Typhoeus/Hydra에서 문제가 발생하지는 않았지만 쉽게 처리 할 수있는 RSS 처리를 위해 작성되었습니다. 잘하면 잘 동작 할 것입니다. 결과를 알려주세요. –

+0

내 시간은 현재 여러 프로젝트로 나뉘어져 있습니다.하지만 제대로 작동하는 것으로 확인되면 다시보고하겠습니다. – MAP

1
난 단지 자바 루비에서 다중 스레드 아무 짓도하지 않은,하지만 그것은 매우 간단 보인다

: http://www.tutorialspoint.com/ruby/ruby_multithreading.htm 당신이 설명한 것과

, 당신은 어떤 큐와 노동자가 필요하지 않습니다 (물론, 나는 확신 당신도 그렇게 할 수는 있지만 많은 유익을 얻을 수 있을지는 의문입니다.) 여러 스레드 사이에 URL을 분할하고 각 스레드가 각 청크를 수행하고 결과로 데이터베이스를 업데이트하게하십시오. 예를 들어, 100 개의 스레드를 생성하고 각 스레드에게 처리 할 1000 개의 데이터베이스 행 범위를 제공하십시오.

스레드가 아닌 프로세스를 처리하려는 경우 100 개의 개별 프로세스를 생성하고 인수로 행을 지정할 수도 있습니다.

URL 상태를 얻으려면, 내가 생각하기에 HTTP HEAD 요청을했다고 생각합니다. 이것은 ruby에서 http://apidock.com/ruby/Net/HTTP/request_head입니다.

0

보석은 응용 프로그램에서 작업을 비동기 적으로 동시에 수행하는 가장 쉬운 방법입니다.