我正在尝试在 Cedar 堆栈上部署 Sinatra 流式 SSE 响应应用程序。不幸的是,虽然它在开发中完美运行,但一旦部署到 Heroku,callback
或 errback
永远不会在调用连接时被调用,导致连接池被陈旧的连接填满(永远不会超时,因为数据仍在服务器端发送给他们。)
来自 Heroku 文档的相关信息:
Long-polling and streaming responses
Cedar supports HTTP 1.1 features such as long-polling and streaming responses. An application has an initial 30 second window to respond with a single byte back to the client. However, each byte transmitted thereafter (either received from the client or sent by your application) resets a rolling 55 second window. If no data is sent during the 55 second window, the connection will be terminated.
If you’re sending a streaming response, such as with server-sent events, you’ll need to detect when the client has hung up, and make sure your app server closes the connection promptly. If the server keeps the connection open for 55 seconds without sending any data, you’ll see a request timeout.
这正是我想要做的——检测客户端何时挂断,并立即关闭连接。然而,Heroku 路由层的一些事情似乎阻止了 Sinatra 像往常一样检测流关闭事件。
可用于复制此内容的一些示例代码:
require 'sinatra/base'
class MyApp < Sinatra::Base
set :path, '/tmp'
set :environment, 'production'
def initialize
@connections = []
EM::next_tick do
EM::add_periodic_timer(1) do
@connections.each do |out|
out << "connections: " << @connections.count << "\n"
end
puts "*** connections: #{@connections.count}"
end
end
end
get '/' do
stream(:keep_open) do |out|
@connections << out
puts "Stream opened from #{request.ip} (now #{@connections.size} open)"
out.callback do
@connections.delete(out)
puts "Stream closed from #{request.ip} (now #{@connections.size} open)"
end
end
end
end
我在 http://obscure-depths-3413.herokuapp.com/ 上放置了一个示例应用程序使用说明问题的代码。当你连接时,连接数量会增加,但当你断开连接时,它们永远不会下降。 (带有 Gemfile 等的完整演示源位于 https://gist.github.com/mroth/5853993 )
我无能为力地试图调试这个。有人知道怎么解决吗?
附言似乎有一个 similar bug in Sinatra但它在一年前就修好了。此外,此问题仅发生在 Heroku 的生产环境中,但在本地运行时工作正常。
附注 2。当遍历连接对象时也会发生这种情况,例如添加以下代码:
EM::add_periodic_timer(10) do
num_conns = @connections.count
@connections.reject!(&:closed?)
new_conns = @connections.count
diff = num_conns - new_conns
puts "Purged #{diff} connections!" if diff > 0
end
在本地运行良好,但连接在 Heroku 上从未显示为已关闭。
最佳答案
更新:在直接与 Heroku 路由团队(他们很棒!)合作后,这个问题现在已在他们的新路由层中得到修复,并且应该可以在任何平台上正常工作。
关于ruby - Heroku 上的 Sinatra/Thin 未检测到 HTTP 流连接 (SSE) 客户端断开连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17285961/