3

私は、Redis チャネルをサブスクライブし、Server Sent Events を使用してメッセージをクライアントにプッシュする Rack ミドルウェアの構築に取り組んでいます。Sinatra は、これを行うための優れた DSL を提供しています。実際の例がありますが、私が直面している問題は、クライアントが 7 または 8 になるとパフォーマンスが大幅に低下することです。リクエスト間でRedis接続を再利用しようとすると、サーバーが「デッドロック」するという問題にも遭遇しました。

私は Thin を使用してアプリを提供しています (内部で EventMachine を使用しています)。Sinatra DSL は既に EventMachine との同時実行を処理していると思いましたが、これは自分で実装する必要があるのでしょうか? 誰かが Puma のようなマルチスレッド サーバーを使用したい場合に備えて、EventMachine ベースのサーバー (Thin、Rainbows!) だけに自分自身を制限したくありません。コードの同時実行性を高めるにはどうすればよいですか?

require 'redis'
require 'sinatra/base'

class SSE < Sinatra::Base

  def send_message(json)
    "id: #{Time.now}\n" +
    "data: #{json}" +
    "\r\n\n"
  end

  get '/channels/:id/subscribe', provides: 'text/event-stream' do
    channel_id = params['id']
    stream(:keep_open) do |connection|
      Redis.new.subscribe("channels:#{channel_id}") do |on|
        on.message do |channel, json|
          connection << send_message(json)
        end
      end
    end
  end

end
4

2 に答える 2

1

思い当たることがいくつかあるので、順不同で繰り返します。

私は Thin を使用してアプリを提供しています (内部で EventMachine を使用しています)。Sinatra DSL は既に EventMachine との同時実行を処理していると思いましたが、これは自分で実装する必要があるのでしょうか?

おっしゃるとおり、Thin は EventMachine を使用しています。ただし、EventMachine (またはその他のリアクター) では、同期操作を実行すると、リアクター全体が停止します。したがって、期待どおりの同時実行性を真に得るには、アプリケーション全体で EventMachine の使用を継続する必要があります。

pub/sub をサポートする EventMachine 対応の Redis クライアントについては、em-hiredisをチェックしてください。

誰かが Puma のようなマルチスレッド サーバーを使用したい場合に備えて、EventMachine ベースのサーバー (Thin、Rainbows!) だけに制限したくありません。

私が言おうとしていることを試したことはありませんが、EventMachine を使用しないサーバー内で EventMachine を使用する際に問題が発生することはないと思います。独自の EM を開始することを忘れないでください。おそらくconfig.ruで?

リクエスト間でRedis接続を再利用しようとすると、サーバーが「デッドロック」するという問題にも遭遇しました

これが発生している理由は、'/channels/:id/subscribe' への各呼び出しが Redis への新しい接続を開いているためだと思います。あなたはそれらの非常に多くを開くことができます。Redis.newアプリケーションの共有接続へのリファクタリングを検討してください。一度だけ開きます。単一の Redis 接続で複数の pub/sub を処理できる必要があります。

ほんの少しの考えです。お役に立てば幸いです。

于 2013-10-05T18:10:09.713 に答える