我正在尝试从Ruby(1.9.1p378)Sinatra(1.0)Rack(1.2.1)应用程序中流式传输文本数据(XML / JSON)。建议的解决方案(例如Is there a way to flush html to the wire in Sinatra)似乎不起作用 - 当我产生某些无限流的元素时(例如来自%w(foo bar).cycle
),服务器就会阻塞。我尝试webrick
和thin
作为服务器。
有关完成此操作的任何建议吗?我应该使用http://sinatra.rubyforge.org/api/classes/Sinatra/Streaming.html,如果是这样,我将如何在我的应用程序中使用它?
答案 0 :(得分:31)
从Sinatra 1.3开始,您还可以使用新的流API:
get '/evented' do
stream(:keep_open) do |out|
EventMachine::PeriodicTimer.new(1) { out << "#{Time.now}\n" }
end
end
答案 1 :(得分:19)
Webrick和Thin都不支持这种流式传输方式。你可以试试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进行流式传输:here是一个补丁。
答案 2 :(得分:7)
正如Colin所说,Goliath可以传输响应数据以及传入(大文件上传)。回购中有一个示例,用于将数据流式传输到客户端:https://github.com/postrank-labs/goliath/blob/master/examples/stream.rb
您可以轻松地连接任何其他数据流以将数据推送到客户端,而不是计时器。例如,您可以将AMQP队列或任何其他消息队列直接连接到Goliath,并让它充当该数据的HTTP前端。
答案 3 :(得分:5)
你一定要看一下机架Goliath web server。它支持开箱即用的流媒体。我用它来制作一个firehose风格的流式api。
Goliath既是app服务器又是a 轻量级框架旨在满足 以下目标:完全 异步处理,中间件 支持,简单配置, 高性能,可以说是最多的 重要的是,可读性和可维护性 代码。