【问题标题】:Sending mass emails without background job在没有后台工作的情况下发送大量电子邮件
【发布时间】:2014-01-10 02:40:59
【问题描述】:

我想从我的 Rails 应用程序自动向用户列表发送电子邮件。 数量范围从真正的少数用户 (5-10) 到用户组 (50-70)。 最大值将是所有用户(当前为 5000)。

我知道发送电子邮件会阻塞 Rails 应用程序,因此发送电子邮件应该借助排队系统和后台作业来完成,例如通过使用 DelayedJob、Resque 或 Sidekiq。

不幸的是,拥有这样一个后台作业需要 Heroku 平台上的工作进程。由于成本增加(至少在开始时),我想避免这种情况。

我可以采取任何替代方法吗?例如,第二个 Rails 应用程序只有一个工作进程,它只处理电子邮件(我猜这也会导致付费工作进程)?

是否可以通过 SendGrid、MailGun 或与 Heroku 完美集成的任何其他服务在没有此类工作进程的情况下发送大量电子邮件?

【问题讨论】:

  • 你的 Rails 控制器在 Heroku 中超时,你不能这样做
  • 有没有办法只在队列中有作业时运行工作人员测功机?我想避免运行一个在 99% 的时间内无事可做的工人测功机。或者这是否已经由 Heroku 以这种方式自动完成?
  • 这可能会有所帮助github.com/phoet/freemium
  • 是的,使用适合您需求的租用火
  • 我将 autoscaler gem 与 Sidekiq 一起使用 - rubygems.org/gems/autoscaler 它会在您需要时启动一个工作器,然后再次将其关闭。效果很好。

标签: ruby-on-rails ruby ruby-on-rails-3 email heroku


【解决方案1】:

向@phoet 提供链接的道具

我们在 Heroku 上也有类似的想法,我们认为它是免费的。结果他们向我们收取了scheduler 小时的费用......但我们做了以下事情:


Resque

Resque 是一个在 Rails 上运行的队列系统,用于在 Redis 中对项目进行排队。完全推荐给use this on Heroku,非常高效且可扩展

它是这样工作的:

  1. 将“数据”(通常是 ID)发送到 resque 队列
  2. Resque 将 ID 发送到 Redis
  3. Resque rake 作业处理 Redis 队列
  4. 在处理队列时执行邮件发送(将电子邮件发送到 Mandrill / SendGrid)

有一个队列的原因正如@apneadiving 所说 - 你的控制器将超时并且(更重要的是),你的 Rails 应用程序将锁定直到进程完成

Resque 上有一个非常好的 Railscast here:


代码

这只是基本代码 - 如果您愿意,可以添加更多代码:

    #app/controllers/messages_controller.rb
    def send_message
        id = params[:id]
        message = Message.find(id).broadcast!

        flash[:notice] = "Broadcast Queued!"
        redirect_to root_path
    end

   #app/models/message.rb
   def broadcast!
         self.subscribers.each do |subscriber|
             Resque.enqueue(MailoutQueue, id, subscriber.id, queue.id)
         end
   end

   #app/workers/mailout_queue.rb
   class MailoutQueue
        @queue = :mailer
        def self.perform(message_id, recipient_id, queue_id)
                MessageMailer.send_message(message_id, recipient_id).deliver
        end
   end

class MessageMailer < ActionMailer::Base
        default from: '****************'

        def send_message(message_id, subscriber_id)

                #Declarations
                @message = Message.find(message_id)
                @subscriber = Subscriber.find(subscriber_id)

                #Send
                mail(:to => @subscriber.email, :subject => @message.title)

        end        

end

【讨论】:

  • 感谢 Resque 的详细解释。但是,我现在选择了 DelayedJob,因为我找到了使用无工作 gem (github.com/lostboy/workless) 在 Heroku 上自动扩展工作进程的解决方案。 @apneadiving 建议使用 Hirefire gem (github.com/meskyanichi/hirefire),它也可以与 Resque 一起使用,但是,gem 本身不再维护,我无法让它在我的 Rails 设置中正常工作。有大约 10 美元/月/应用程序的付费服务应该可以正常工作。我只能建议使用自动缩放解决方案以节省成本。
  • 没问题!您必须记住,DelayedJob 依赖于 ActiveRecord,因此只能处理比 Resque 少得多的对象数量。 IMO、Resque 和 Redis 是迄今为止最具扩展性的排队解决方案,但如果你能与 DJ 一起使用,那也太棒了!!
  • 我完全理解由于Redis和ActiveRecord的不同,DelayedJob比Resque慢的问题。如果您找到任何可以在 Heroku 上自动扩展 Resque 工作进程的解决方案,我也会感兴趣。
  • 好的!感谢您的回复:) 我一定会告诉你的!
【解决方案2】:

看看这里 - https://github.com/stephenb/sendgrid#delivering-to-multiple-recipients

这允许您通过一个 SMTP 调用发送多封电子邮件。

【讨论】:

    猜你喜欢
    • 2011-11-12
    • 1970-01-01
    • 2012-01-06
    • 2011-06-06
    • 2015-01-03
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多