1

私は現在、ユーザーが Gmail 経由でサインインできるようにする Ruby on Rails アプリを構築しており、受信トレイに常に IDLE 接続しています。メールは、Gmail の受信トレイに届くとすぐにアプリに届く必要があります。

現在、実装に関して次のような問題があり、いくつかの問題を解決するために本当に助けが必要です。

現時点では、Rails アプリが起動すると、IDLE 接続を維持するためにループ内で認証および実行されるスレッドがユーザーごとに作成されます。

スレッドは 10 ~ 15 分ごとに「IDLE をバウンス」し、IDLE 接続が維持されるように少量のデータが転送されます。

私が考える主な問題は、スケーラビリティと、アプリが Postgres に接続する数です。各スレッドには Postgres への接続が必要なようです。これは、Heroku では最大接続数 (基本の場合は 20、それ以降のプランの場合は 500) によって大幅に制限されます。

次の点で本当に助けが必要です。

  • これらすべての IDLE 接続を維持しながら、データベースに必要なスレッドと接続の数を減らす最善の方法は何ですか?
    • 注: Gmail への更新トークンが不足すると、ユーザー トークンの更新が発生する可能性があるため、データベースへのアクセスが必要になります。
  • これを実装する方法について他に提案はありますか?

編集:

この質問の OP に似たものを実装しました: Ruby IMAP IDLE concurrency - how to attach?

4

2 に答える 2

5

IMAP セッションごとに新しいスレッドを作成する必要はありません。これらは単一のスレッドで実行できます。

すべてのユーザーとその IMAP セッションの配列 (またはハッシュ) を維持します。スレッドを生成し、そのスレッドで IDLE キープアライブを各接続に次々に送信します。ループを定期的に実行します。これにより、現在のアプローチよりもはるかに多くの並行性が確実に得られます。

長期的なアプローチは、EventMachine を使用することです。これにより、同じスレッドで多くの IMAP 接続を使用できるようになります。同じプロセスで Web リクエストを処理している場合は、Event Machine 用に別のスレッドを作成する必要があります。このアプローチにより、驚異的な同時実行性が得られます。Eventmachine 互換の IMAP ライブラリについては、 https://github.com/ConradIrwin/em-imapを参照してください。

于 2013-07-22T10:15:18.280 に答える
2

Rails で EventMachine を起動する

あなたは Heroku を使用しているので、おそらく EventMachine をすでに起動している Thin を使用しています。ただし、別のホストに移動して他の Web サーバー (Phusion Passenger など) を使用する場合は、Rails 初期化子を使用して EventMachine を開始できます。

module IMAPManager
  def self.start
    if defined?(PhusionPassenger)
      PhusionPassenger.on_event(:starting_worker_process) do |forked|
      # for passenger, we need to avoid orphaned threads
        if forked && EM.reactor_running?
          EM.stop
        end
        Thread.new { EM.run }
        die_gracefully_on_signal
      end
    else
      # faciliates debugging
      Thread.abort_on_exception = true
      # just spawn a thread and start it up
      Thread.new { EM.run } unless defined?(Thin)
      # Thin is built on EventMachine, doesn't need this thread
    end
  end

  def self.die_gracefully_on_signal
    Signal.trap("INT")  { EM.stop }
    Signal.trap("TERM") { EM.stop }
  end
end

IMAPManager.start

( Joshua Silerのブログ投稿から引用。)

1 つのつながりを共有する

あなたが持っているものは良いスタートですが、データベースへの O(n) 接続を持つ O(n) スレッドを持つことは、おそらくスケーリングが難しいでしょう。ただし、ほとんどの場合、これらのデータベース接続は何もしていないため、1 つのデータベース接続を共有することを検討してください。

@Deepak Kumar が述べたように、EM IMAP アダプターを使用して IMAP IDLE 接続を維持できます。実際、Rails 内で EM を使用しているため、Rails モデルを変更することで、Rails のデータベース接続プールを簡単に使用できる場合があります。接続プールの構成の詳細については、こちらを参照してください

于 2013-07-26T15:53:42.527 に答える