我正在尝试在 Cedar 堆栈上部署 Sinatra 流式 SSE 响应应用程序。不幸的是,虽然它在开发中完美运行,但一旦部署到 Herokucallback
或errback
在调用连接时永远不会被调用,导致连接池被陈旧的连接填满(永远不会超时,因为数据仍在服务器上发送给它们边。)
Heroku 文档中的相关信息:
长轮询和流式响应
Cedar 支持 HTTP 1.1 功能,例如长轮询和流式响应。应用程序有一个初始的 30 秒窗口,用于向客户端返回一个字节。但是,此后传输的每个字节(从客户端接收或由您的应用程序发送)都会重置一个滚动的 55 秒窗口。如果在 55 秒窗口内没有发送数据,则连接将终止。
如果您正在发送流式响应,例如服务器发送的事件,您需要检测客户端何时挂断,并确保您的应用服务器及时关闭连接。如果服务器保持连接打开 55 秒而不发送任何数据,您将看到请求超时。
这正是我想做的——检测客户端何时挂断,并立即关闭连接。然而,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)
我正在尝试调试这个。谁知道怎么修它?
PS Sinatra 中似乎也有类似的错误,但在一年前已修复。此外,此问题仅发生在 Heroku 的生产中,但在本地运行时可以正常工作。
PS2。迭代连接对象时也会发生这种情况,例如添加以下代码:
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 上从未显示为已关闭。