从Sinatra/Rack应用程序中流式传输数据

22
我正在尝试从一个Ruby(1.9.1p378)Sinatra(1.0)Rack(1.2.1)应用程序中流式传输文本数据(XML / JSON)。建议的解决方案(例如Sinatra中有一种将html刷新到线路上的方法吗?)似乎不起作用 - 当我产生某些无限流的元素时(例如来自%w(foo bar).cycle),服务器就会阻止。我尝试了webrickthin作为服务器。

如何完成这个任务?我应该使用Sinatra的Streaming功能吗?如果是的话,我该如何在我的应用程序中使用它?

4个回答

31

从Sinatra 1.3开始,你也可以使用新的流式API:

get '/evented' do
  stream(:keep_open) do |out|
    EventMachine::PeriodicTimer.new(1) { out << "#{Time.now}\n" }
  end
end

Konstantin - 这适用于所有Web服务器还是只适用于像Thin这样的事件驱动Web服务器?我在寻找使用像Passenger这样的标准服务器的新流API示例代码时遇到了麻烦... - wchrisjohnson
1
只有使用事件驱动的Web服务器,例如Thin、Rainbows!或Ebb - 但是Puma计划支持此功能。 - Konstantin Haase
不使用 :keep_open 的流式传输适用于所有服务器,但不会在所有服务器上进行流式传输(特别是在Webrick上不行)。 - Konstantin Haase
如果你告诉它保持打开状态,那么如何关闭它呢?也就是说,我想在传输完所有内容之前一直保持打开状态,然后再关闭。 - Christian Johansen

19

既 Webrick 也不支持那种方式的流媒体传输。您可以尝试使用 Mongrel 或者 Unicorn。如果您想使用 Thin 或 Rainbows!,则需要钩入事件循环以实现流媒体传输:

require 'sinatra'

class Stream
  include EventMachine::Deferrable
  def initialize
    @counter = 0
  end

  def each(&block)
    if @counter > 10
      succeed
    else
      EM.next_tick do
        yield counter
        each(&block)
      end
    end
  end
end

get '/' do
  Stream.new
end

我最近编写了一个这样的EventSource实现:

require 'sinatra'

class EventStream
  include EventMachine::Deferrable
  def each
    count = 0
    timer = EventMachine::PeriodicTimer.new(1) do
      yield "data: #{count += 1}\n\n"
    end
    errback { timer.cancel }
  end
end

get '/' do
  EventMachine.next_tick do
    request.env['async.callback'].call [
      200, {'Content-Type' => 'text/event-stream'},
      EventStream.new ]
  end
  [-1, {}, []]
end

如果您想使用Webrick进行流式传输:这里有一个补丁。


2
Thin具有在流式传输时能够回答其他请求的优点。 - Konstantin Haase

7
正如Colin所提到的那样,Goliath可以流式传输响应数据和输入数据(大文件上传)。示例repo中有一个将数据流式传输到客户端的示例:https://github.com/postrank-labs/goliath/blob/master/examples/stream.rb 您可以轻松地将任何其他数据流连接到客户端,而不是定时器。例如,您可以将AMQP队列或任何其他消息队列直接连接到Goliath,并让它作为该数据的HTTP前端。

有没有关于Goliath的社区?整个项目似乎都是非常前沿的,我对一些事情还不确定,比如支持分块和在回调中识别请求... - yawn
1
邮件列表是一个很好的起点:https://groups.google.com/forum/#!forum/goliath-io - 这里有一群很好的人在关注它。一些正在使用 Goliath 构建的更有趣的应用程序不幸地没有公开,但随着时间的推移,这种情况将会改变。这是前沿技术。 :-) - igrigorik

5
你一定要看看可以机架安装的 Goliath web server。它支持开箱即用的流式传输。我正在使用它来进行类似消防水龙带风格的流媒体API。

Goliath既是应用服务器,也是一个轻量级框架,旨在实现以下目标:完全异步处理、中间件支持、简单配置、高性能,以及最重要的可读性和可维护性。


非常有趣的项目!感谢提示! - yawn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接