2010-05-14 5 views
3

Je consomme divers services Web XML-sur-HTTP renvoyant de gros fichiers XML (> 2 Mo). Quelle serait la bibliothèque http ruby ​​la plus rapide pour réduire le temps de téléchargement?Bibliothèque http rapide ruby ​​pour les gros téléchargements XML

Caractéristiques requises:

  • à la fois GET et POST demande

  • gzip/dégonfler téléchargements (Accept-Encoding: deflate, gzip) - très important

Je pense entre:

  • open-uri

  • Net :: HTTP

  • trottoir

mais vous pouvez aussi venir avec d'autres suggestions.

P.S. Pour analyser la réponse, j'utilise un analyseur de Nokogiri, donc je n'ai pas besoin d'une solution intégrée comme rest-client ou hpricot.

+0

Merci à tous pour vos bonnes et intéressantes réponses. Je vais donner 'accepter la réponse' à Ben, car sa réponse est la plus proche de ce que je cherche. –

Répondre

3

http://github.com/pauldix/typhoeus

peut-être la peine de vérifier. Il est conçu pour des téléchargements parallèles volumineux et rapides et est basé sur libcurl, donc c'est assez solide. Cela dit, tester Net :: HTTP et voir si la performance est acceptable avant de faire quelque chose de plus compliqué.

1

Le téléchargement le plus rapide est probablement un #read sur l'objet IO, qui englobe tout dans une seule chaîne. Après cela, vous pouvez appliquer votre traitement. Ou avez-vous besoin d'avoir le fichier traité pendant le téléchargement?

+0

Je ne veux pas que ce soit si compliqué. Sur votre solution, je devrais écrire mon propre wrapper http, avec la compression gzip/deflate et le support post. –

+0

Je ne comprends pas ce que vous pensez être si compliqué à propos de ma suggestion. Utiliser IO # lire avec Net: HTTP pour lire le tout dans une chaîne est probablement aussi simple que vous pouvez le télécharger. –

17

Vous pouvez utiliser EventMachine et em-http pour diffuser le 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 

Il est un peu faible niveau peut-être, mais probablement l'option la plus performante pour toute taille de document. Nourrissez-le de centaines de megs et cela ne remplira pas votre mémoire, comme le ferait n'importe quelle solution non-streaming (tant que vous ne conservez pas une grande partie du document que vous chargez, mais c'est de votre côté).

4

J'ai trouvé la réponse de Theo en cherchant une solution pour un cas d'utilisation similaire. J'ai trouvé qu'avec un petit tweak son exemple donné marchera, mais tel qu'il est ne fonctionne pas pour moi; il coupe prématurément l'analyse lorsque le http.callback a été déclenché. Mais merci pour l'inspiration Theo!

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 
Questions connexes