Быстрая библиотека ruby ​​http для больших загрузок XML - PullRequest
3 голосов
/ 14 мая 2010

Я использую различные веб-сервисы XML-over-HTTP, возвращающие большие XML-файлы (> 2 МБ). Какая бы самая быстрая библиотека ruby ​​http для сокращения времени загрузки?

необходимые функции:

  • запросы GET и POST

  • gzip / deflate downloads (Accept-Encoding: deflate, gzip) - очень важно

Я думаю между:

  • открытая * 1020 URI *

  • Net :: HTTP

  • Снаряженная

но вы также можете прийти с другими предложениями.

P.S. Для разбора ответа я использую парсер pull от Nokogiri, поэтому мне не нужно интегрированное решение, такое как rest-client или hpricot.

Ответы [ 4 ]

17 голосов
/ 15 мая 2010

Вы можете использовать EventMachine и em-http для потоковой передачи XML:

require 'rubygems'
require 'eventmachine'
require 'em-http'
require 'nokogiri'

# this is your SAX handler, I'm not very familiar with
# Nokogiri, so I just took an exaple from the RDoc
class SteamingDocument < Nokogiri::XML::SAX::Document
  def start_element(name, attrs=[])
    puts "starting: #{name}"
  end

  def end_element(name)
    puts "ending: #{name}"
  end
end

document = SteamingDocument.new
url = 'http://stackoverflow.com/feeds/question/2833829'

# run the EventMachine reactor, this call will block until 
# EventMachine.stop is called
EventMachine.run do
  # Nokogiri wants an IO to read from, so create a pipe that it
  # can read from, and we can write to
  io_read, io_write = IO.pipe

  # run the parser in its own thread so that it can block while
  # reading from the pipe
  EventMachine.defer(proc {
    parser = Nokogiri::XML::SAX::Parser.new(document)
    parser.parse_io(io_read)
  })

  # use em-http to stream the XML document, feeding the pipe with
  # each chunk as it becomes available
  http = EventMachine::HttpRequest.new(url).get
  http.stream { |chunk| io_write << chunk }

  # when the HTTP request is done, stop EventMachine
  http.callback { EventMachine.stop }
end

Возможно, это немного низкоуровневый, но, вероятно, самый эффективный вариант для любого размера документа. Накормите его сотнями мегабайт, и он не заполнит вашу память, как любое не потоковое решение (если вы не будете придерживаться большей части загружаемого документа, но это на вашей стороне). 1008 *

4 голосов
/ 08 ноября 2011

Я нашел ответ Тео, когда искал решение для подобного варианта использования. Я обнаружил, что с небольшим изменением его приведенный пример будет работать, но, как он есть, у меня не сработало; преждевременное отключение синтаксического анализа при запуске http.callback. Но спасибо за вдохновение Тео!

require 'rubygems'
require 'eventmachine'
require 'em-http'
require 'nokogiri'

# this is your SAX handler, I'm not very familiar with
# Nokogiri, so I just took an exaple from the RDoc
class SteamingDocument < Nokogiri::XML::SAX::Document
  def start_element(name, attrs=[])
    puts "starting: #{name}"
  end

  def end_element(name)
    puts "ending: #{name}"
  end

  def end_document
    puts "should now fire"
  end
end

document = SteamingDocument.new
url = 'http://stackoverflow.com/feeds/question/2833829'

# run the EventMachine reactor, this call will block until 
# EventMachine.stop is called
EventMachine.run do
  # Nokogiri wants an IO to read from, so create a pipe that it
  # can read from, and we can write to
  io_read, io_write = IO.pipe

  # run the parser in its own thread so that it can block while
  # reading from the pipe
  EventMachine.defer(proc {
    parser = Nokogiri::XML::SAX::Parser.new(document)
    parser.parse_io(io_read)
  }, proc { EventMachine.stop })

  # use em-http to stream the XML document, feeding the pipe with
  # each chunk as it becomes available
  http = EventMachine::HttpRequest.new(url).get
  http.stream { |chunk| io_write << chunk }

  # when the HTTP request is done, stop EventMachine
  http.callback { io_write.close }
end
3 голосов
/ 14 мая 2010

http://github.com/pauldix/typhoeus

может стоить проверить. Он предназначен для больших и быстрых параллельных загрузок и основан на libcurl, поэтому он довольно надежный.

Тем не менее, проверьте Net :: HTTP и посмотрите, приемлема ли производительность, прежде чем делать что-то более сложное.

1 голос
/ 15 мая 2010

Самая быстрая загрузка - это, вероятно, #read объекта IO, который в целом превращается в одну строку. После этого вы можете применить свою обработку. Или вам требуется обработать файл во время загрузки?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...