【问题标题】:Ruby on Rails with IMAP IDLE for multiple accounts带有 IMAP IDLE 的 Ruby on Rails 用于多个帐户
【发布时间】:2013-07-14 10:44:47
【问题描述】:

我目前正在构建一个 Ruby on Rails 应用程序,该应用程序允许用户通过 Gmail 登录,并且它与他们的收件箱有持续的 IDLE 连接。电子邮件需要在进入 Gmail 收件箱后立即送达应用。

目前我在实施方面有以下几点,以及一些我确实需要帮助解决的问题。

目前,当 Rails 应用启动时,它会为每个用户创建一个线程,该线程进行身份验证并循环运行以保持 IDLE 连接处于活动状态。

每隔 10-15 分钟,线程会“反弹 IDLE”,以便传输少量数据以确保 IDLE 连接保持活动状态。

我认为主要问题在于可扩展性以及应用程序与 Postgres 的连接数。似乎每个线程都需要连接到 Postgres,这将在 Heroku 上受到最大连接数的严重限制(基本连接数为 20,之后的任何计划为 500)。

我真的需要以下帮助:

  • 保持所有这些空闲连接处于活动状态但减少数据库所需的线程和连接数的最佳方法是什么?
    • 注意:如果 Gmail 的刷新令牌用完,可能会发生用户令牌刷新,因此这需要访问数据库
  • 对于如何实施,还有其他建议吗?

编辑:

我在这个问题中实现了类似于 OP 的东西:Ruby IMAP IDLE concurrency - how to tackle?

【问题讨论】:

    标签: ruby-on-rails ruby imap


    【解决方案1】:

    无需为每个 IMAP 会话生成一个新线程。这些可以在一个线程中完成。

    维护所有用户及其 IMAP 会话的数组(或哈希)。生成一个线程,在该线程中,一个接一个地向每个连接发送 IDLE keep-alive。定期运行循环。这肯定会给您带来比当前方法更多的并发性。

    一个长期的方法是使用 EventMachine。这将允许在同一个线程中使用许多 IMAP 连接。如果您在同一进程中处理 Web 请求,则应为 Event Machine 创建一个单独的线程。这种方法可以为您提供惊人的并发性。有关 Eventmachine 兼容的 IMAP 库,请参阅 https://github.com/ConradIrwin/em-imap

    【讨论】:

      【解决方案2】:

      在 Rails 中启动 EventMachine

      由于您在 Heroku 上,您可能正在使用 Thin,它已经为您启动了 EventMachine。但是,如果您曾经移动到另一台主机并使用其他一些 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 的 blog post。)

      共享 1 个连接

      您所拥有的是一个好的开始,但是拥有 O(n) 个线程和 O(n) 个与数据库的连接可能很难扩展。但是,由于这些数据库连接中的大多数大部分时间都没有执行任何操作,因此可能会考虑共享一个数据库连接。

      正如@Deepak Kumar 所提到的,您可以使用 EM IMAP 适配器来维护 IMAP IDLE 连接。事实上,由于您在 Rails 中使用 EM,因此您可以通过 Rails 模型进行更改,从而简单地使用 Rails 的数据库连接池。更多关于配置连接池的信息可以查看here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-18
        • 1970-01-01
        • 1970-01-01
        • 2011-05-31
        • 1970-01-01
        • 2010-11-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多