2012-02-22 10 views
7

Niedawno zacząłem uczyć się o robotach sieciowych i zbudowałem próbny robot z Ruby, Anemone i Mongodb do przechowywania. Testuję robota na ogromnej publicznej stronie z prawdopodobnie miliardami linków.Ruby, Mongodb, Anemone: robota sieciowego z możliwym wyciekiem pamięci?

Crawler.rb indeksuje poprawne informacje, chociaż kiedy sprawdzam użycie pamięci w monitorze aktywności, pokazuje ona stale rosnącą pamięć. Uruchomiłem przeszukiwacz tylko na około 6-7 godzin, a pamięć pokazuje 1,38 GB dla mongody i 1,37 GB dla procesu Ruby. Wydaje się, że rośnie około 100 MB co godzinę.

Wygląda na to, że mogę mieć wyciek pamięci? Czy jest to bardziej optymalny sposób, w jaki mogę osiągnąć to samo indeksowanie bez utraty kontroli nad pamięcią, aby mogła działać dłużej?

# Sample web_crawler.rb with Anemone, Mongodb and Ruby. 

require 'anemone' 

# do not store the page's body. 
module Anemone 
    class Page 
    def to_hash 
     {'url' => @url.to_s, 
     'links' => links.map(&:to_s), 
     'code' => @code, 
     'visited' => @visited, 
     'depth' => @depth, 
     'referer' => @referer.to_s, 
     'fetched' => @fetched} 
    end 
    def self.from_hash(hash) 
     page = self.new(URI(hash['url'])) 
     {'@links' => hash['links'].map { |link| URI(link) }, 
     '@code' => hash['code'].to_i, 
     '@visited' => hash['visited'], 
     '@depth' => hash['depth'].to_i, 
     '@referer' => hash['referer'], 
     '@fetched' => hash['fetched'] 
     }.each do |var, value| 
     page.instance_variable_set(var, value) 
     end 
     page 
    end 
    end 
end 


Anemone.crawl("http://www.example.com/", :discard_page_bodies => true, :threads => 1, :obey_robots_txt => true, :user_agent => "Example - Web Crawler", :large_scale_crawl => true) do | anemone | 
    anemone.storage = Anemone::Storage.MongoDB 

    #only crawl pages that contain /example in url 
    anemone.focus_crawl do |page| 
    links = page.links.delete_if do |link| 
     (link.to_s =~ /example/).nil? 
    end 
    end 

    # only process pages in the /example directory 
    anemone.on_pages_like(/example/) do | page | 
    regex = /some type of regex/ 
    example = page.doc.css('#example_div').inner_html.gsub(regex,'') rescue next 

    # Save to text file 
    if !example.nil? and example != "" 
     open('example.txt', 'a') { |f| f.puts "#{example}"} 
    end 
    page.discard_doc! 
    end 
end 
+0

Czy wymyśliłeś przyczynę wycieku? Jeśli uważasz, że to błąd w Anemone, czy zgłosiłeś to na swoim [trackerze problemów] (https://github.com/chriskite/anemone/issues)? –

+0

Powiązane problemy wymienione w module śledzenia problemów z anemonem to: [wyciek pamięci?] (Https://github.com/chriskite/anemone/issues/49), [wyciek pamięci lub niewydajna obsługa pamięci] (https://github.com/chriskite/anemone/issues/29) i [Napraw błędy OutOfMemory dla dużych witryn] (https://github.com/chriskite/anemone/pull/30) –

+0

Zgłosiłem to w tym samym czasie, co publikowanie tutaj na SO. Udało mi się zaindeksować to, co wymagało moje zadanie, dodając sugerowane poprawki, co spowodowało, że moje indeksowanie trwało znacznie dłużej, chociaż zużycie pamięci RAM rosło stale, ale nie tak szybko, jak było wcześniej. Nadal nie jestem pewien, co powoduje wyciek pamięci. – viotech

Odpowiedz

3

Mam również problem z tym, ale używam redis jako datastore.

to mój robot:

require "rubygems" 

require "anemone" 

urls = File.open("urls.csv") 
opts = {discard_page_bodies: true, skip_query_strings: true, depth_limit:2000, read_timeout: 10} 

File.open("results.csv", "a") do |result_file| 

    while row = urls.gets 

    row_ = row.strip.split(',') 
    if row_[1].start_with?("http://") 
     url = row_[1] 
    else 
     url = "http://#{row_[1]}" 
    end 
    Anemone.crawl(url, options = opts) do |anemone| 
     anemone.storage = Anemone::Storage.Redis 
     puts "crawling #{url}"  
     anemone.on_every_page do |page| 

     next if page.body == nil 

     if page.body.downcase.include?("sometext") 
      puts "found one at #{url}"  
      result_file.puts "#{row_[0]},#{row_[1]}" 
      next 

     end # end if 

     end # end on_every_page 

    end # end crawl 

    end # end while 

    # we're done 
    puts "We're done." 

end # end File.open 

Zgłosiłem poprawkę z here do mojego pliku core.rb w gem anemon:

35  # Prevent page_queue from using excessive RAM. Can indirectly limit ra te of crawling. You'll additionally want to use discard_page_bodies and/or a  non-memory 'storage' option 
36  :max_page_queue_size => 100, 

...

(Poniższy kiedyś w linii 155)

157  page_queue = SizedQueue.new(@opts[:max_page_queue_size]) 

i mam godzinową crona robi:

#!/usr/bin/env python 
import redis 
r = redis.Redis() 
r.flushall() 

, aby utrzymać zużycie pamięci Redis' w dół. Ponownie uruchamiam gigantyczne indeksowanie, więc zobaczymy, jak to działa!

Złożę raport z wynikami ...

1

Robię coś podobnego i myślę, że może właśnie tworzysz mnóstwo danych.

Nie zapisujesz ciała, które powinno pomóc w spełnieniu wymagań dotyczących pamięci.

Jedynym innym ulepszeniem, które mogę wymyślić jest użycie Redis zamiast Mongo, ponieważ okazało się, że jest znacznie bardziej skalowalny dla magazynu Anemone.

Sprawdź rozmiar danych w Mongo - Zauważyłem, że zapisuję ogromną liczbę wierszy.