2013-06-24 10 views
12

CedarスタックにSinatraストリーミングSSE応答アプリケーションをデプロイしようとしています。残念ながら、開発中に完全に動作する間は、一度Herokuにデプロイされると、接続が呼び出されるとcallbackまたはerrbackが呼び出されることはありません。接続プールが古い接続で満たされます。サーバ側)HerokuのドキュメントからSinu/Thin on HerokuでHTTPストリーミング接続(SSE)クライアントの切断が検出されない

Relvant情報:

ロングポーリングやストリーミング応答

シーダーは、ロングポーリングおよびストリーミングの応答としてHTTP 1.1の機能をサポートしています。アプリケーションには、最初の30秒のウィンドウがあり、クライアントに返す単一のバイトで応答します。しかし、それ以降に送信される各バイト(クライアントから受信されるか、アプリケーションによって送信される)は、55秒のローリングウィンドウをリセットします。 55秒間にデータが送信されない場合、接続は終了します。

サーバー送信イベントなどのストリーミング応答を送信する場合は、クライアントがハングアップしたことを検出して、アプリケーションサーバーが接続をすぐに終了するようにする必要があります。サーバーがデータを送信せずに55秒間接続を開いたままにすると、要求のタイムアウトが表示されます。

これはまさに私がやりたいことです。クライアントがハングアップしたときに検出し、すぐに接続を閉じます。しかし、Herokuルーティング層に関する何かが、Sinatraがストリーム終了イベントを正常に検出するのを妨げるようです。これを複製するために使用することができます

いくつかのサンプルコード:私は、問題を示して、このコードを使用してhttp://obscure-depths-3413.herokuapp.com/でサンプルアプリを入れている

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 

。接続すると接続量は増えますが、切断すると決して下がりません。 (Gemfileのデモの完全なソースはhttps://gist.github.com/mroth/5853993です)

私はこの問題をデバッグしようとしています。誰でもそれを修正する方法を知っていますか?

P.S. similar bug in Sinatraがあるようですが、1年前に修正されました。また、この問題は、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の休館との接続は表示されません。

+1

ローカルで実行したときに正常に動作すると言うと、 'foreman start'を必ず使用しましたか? – Shelvacu

+0

Node.jsストリーミングを使用した場合と同じことhttps://gist.github.com/Funfun/6867167 – CodeGroover

答えて

2

アップデート:Herokuルーティングチーム(偉人)と直接作業した後、これは新しいルーティングレイヤーで修正され、どのプラットフォームでも正しく動作するはずです。

1

私は定期的にこのメッセージを受信したときにクライアントが応答する生きている信号を手渡しします。

この単純なチャットの実装https://gist.github.com/tlewin/5708745を見てください。

アプリケーションは、単純なJSONプロトコルを使用してクライアントと通信します。クライアントがalive: trueメッセージを受信すると、アプリケーションは応答をポストバックし、サーバーは最後の通信時間を格納します。

関連する問題