12

Cedar スタックに Sinatra ストリーミング SSE 応答アプリケーションをデプロイしようとしています。残念ながら、開発中は完全に機能しますが、Heroku にデプロイされると、接続が呼び出されたときに呼び出されなかっcallbackたりerrback、接続プールが古い接続でいっぱいになったりします (サーバー上でデータがまだ送信されているため、タイムアウトすることはありません)。側。)

Heroku ドキュメントからの関連情報:

ロングポーリングとストリーミング レスポンス

Cedar は、ロング ポーリングやストリーミング レスポンスなどの HTTP 1.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 にも同様のバグがあったようですが、1 年前に修正されました。また、この問題は 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 では接続が閉じているようには見えません。

4

2 に答える 2

2

更新情報: Heroku ルーティング チーム (素晴らしい人たちです!) と直接協力した結果、これは新しいルーティング レイヤーで修正され、どのプラットフォームでも適切に機能するはずです。

于 2014-09-30T21:03:39.260 に答える