Streaming lento con Thin o sin streaming

Escribí un pequeño script para transmitir un archivo byte por byte con Sinatra y Thin:

#!/usr/bin/env ruby

require 'sinatra'
require "sinatra/streaming"

get '/' do
  stream do |out|
    File.open("/usr/share/doc/ia32-libs/copyright", "r") do |fd|
      fd.each_byte do |byte|
        break if out.closed?
        putc byte.chr
        out << byte.chr unless out.closed?
      end
    end
  end
end

Esto funciona como se esperaba:

% ruby streamer.rb
== Sinatra/1.3.2 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.4.1 codename Chromeo)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4567, CTRL+C to stop


% curl http://127.0.0.1:4567

y el contenido del archivo se escribe en ambos lados en la salida estándar

Si quito la linea putc byte.chr luego el servidor colapsó y tuvo que ser asesinado por kill -9


Otro comportamiento inesperado me golpea si cambio este script a estilo modular y agrego un config.ru:

#!/usr/bin/env ruby

require 'sinatra/base'
require "sinatra/streaming"

class TestStreamer < Sinatra::Base
  helpers Sinatra::Streaming

  get '/' do
    stream do |out|
      File.open("/usr/share/doc/ia32-libs/copyright", "r") do |fd|
        fd.each_byte do |byte|
          break if out.closed?
#          putc byte.chr
          out << byte.chr unless out.closed?
        end
      end
    end
  end
end

config.ru:

$:.unshift(File.join(File.dirname(__FILE__)))

require 'rubygems'
require 'sinatra/base'
require 'streamer_modular'

map '/' do
  run TestStreamer
end

Se pone en marcha:

% thin start
>> Using rack adapter
>> Thin web server (v1.4.1 codename Chromeo)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:3000, CTRL+C to stop

pero cuando estoy haciendo una solicitud, el archivo se envía extremadamente lento en ambos lados y se cierra después de 30 segundos o algo así. Sinatra no se bloquea en este caso.

% time curl -v http://127.0.0.1:3000
* About to connect() to 127.0.0.1 port 3000 (#0)
*   Trying 127.0.0.1... connected
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.21.0 (x86_64-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.15 libssh2/1.2.6
> Host: 127.0.0.1:3000
> Accept: */*
> 
< HTTP/1.1 200 OK
< X-Frame-Options: sameorigin
< X-XSS-Protection: 1; mode=block
< Content-Type: text/html;charset=utf-8
< Connection: close
< Server: thin 1.4.1 codename Chromeo
< 
* Closing connection #0
This package was cre
curl -v http://127.0.0.1:3000  0,01s user 0,00s system 0% cpu 32,559 total

Cuando elimino el stream-helper, el archivo se escribe en la salida estándar en el servidor sin demora:

#!/usr/bin/env ruby

require 'sinatra/base'
require "sinatra/streaming"

class TestStreamer < Sinatra::Base
  helpers Sinatra::Streaming

  get '/' do
#    stream do |out|
    begin
      File.open("/usr/share/doc/ia32-libs/copyright", "r") do |fd|
        fd.each_byte do |byte|
        #  break if out.closed?
          putc byte.chr
        #  out << byte.chr unless out.closed?
        end
      end
    end
  end
end

% ruby -v
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]

% gem list

*** LOCAL GEMS ***

backports (2.6.2)
bundler (1.1.5, 1.1.3)
daemons (1.1.8)
eventmachine (0.12.10)
rack (1.4.1)
rack-protection (1.2.0)
rack-test (0.6.1)
sinatra (1.3.2)
sinatra-contrib (1.3.1)
thin (1.4.1)
tilt (1.3.3)

% gem update
Updating installed gems
Nothing to update

% ls -al /usr/share/doc/ia32-libs/copyright
-rw-r--r-- 1 root root 607403  2. Jan 2012  /usr/share/doc/ia32-libs/copyright

% head -n2 /usr/share/doc/ia32-libs/copyright
This package was created by Daniel Jacobowitz <dan@debian.org> on Sun, Aug
8th, 2004.  It was based on the ia32-libs package by Bdale Garbee

¿Me estoy perdiendo de algo? ¿Puedes reproducir esto y tal vez tienes una solución para mí?

preguntado el 27 de julio de 12 a las 16:07

prueba unicornio como servidor. delgado no funciona con la transmisión - Mike -

Se dice que trabaja en el readme. ¿Se transmite con un buggy delgado? -

Ni idea. Solo estaba volviendo a publicar una no respuesta como comentario para un nuevo usuario. No se le ha visto en 4 días, por lo que es poco probable que pueda aclararlo. -

1 Respuestas

La transmisión byte por byte en Thin en este modo es algo ineficiente, ya que se necesita mucha programación y aplazamiento debido a que Thin se basa en EventMachine (de ahí el comentario de Mike sobre la transmisión que no funciona en Thin, Mike probablemente tiene experiencia en Rails donde dicha transmisión en Thin de hecho no funciona).

Sin embargo, Thin (y cualquier servidor Rack) debería poder transmitir un archivo directamente:

get '/' do
  File.open("/usr/share/doc/ia32-libs/copyright", "r")
end

Respondido el 04 de Septiembre de 12 a las 10:09

Desafortunadamente, el archivo de derechos de autor es solo un ejemplo. Habrá /dev/random en producción. Además, necesito reducir mi velocidad de escritura de acuerdo con la velocidad con la que se vuelve a llenar la fuente. Lo siento, olvidé mencionar esto - krissi

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.