ruby – HTTP流连接(SSE)客户端断开未检测到Sinatra / Thin在Heroku

我试图在雪松堆栈上部署一个Sinatra流SSE响应应用程序.不幸的是,当它在开发中完美地工作时,一旦部署到Heroku,调用连接时,回调或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的生产中,但在本地运行时工作正常.

P.S.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路由团队(谁是好人!)完成工作后,现在已经在其新的路由层中修复,并且应该在任何平台上正常工作.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...