【问题标题】:Rails - How do I prevent Sidekiq from slowing down the server?Rails - 如何防止 Sidekiq 降低服务器速度?
【发布时间】:2020-07-01 17:44:41
【问题描述】:

我每天早上都会向客户发送一份简报(大约 1 万封电子邮件),有时会发生这种 Sidekiq 作业占用大量 CPU/内存性能,而网站(Rails 应用程序)没有运行并面临停电。

当我查看 Sidekiq 仪表板时,我发现时事通讯存在一些问题(可能是无效的电子邮件地址,并且 Sidekiq 反复尝试再次发送?)并且它被卡住了。

如何防止这种行为并防止重复 Sidekiq 任务(我认为这是突破的问题)?

这是我的代码:

耙任务:

namespace :mailer do  desc "Carrier blast - morning"
  task :newsletter_morning => [:environment] do                                            
    NewslettertJob.perform_later
  end
end

工作定义:

class NewslettertJob < ApplicationJob
  def perform
    ...
    NewsletterMailer.morning_blast(data).deliver_now
  end
end

NewsletterMailer:

class NewsletterMailer < ApplicationMailer
  def morning_blast(data)
    ...
    customers.each do |customer|
      yield customer, nil; next if customer.email.blank?

      begin
        Retryable.retryable( tries: 1, sleep: 30, on: [Net::OpenTimeout, Net::SMTPAuthenticationError, Net::SMTPServerBusy]) do
          send_email(customer.email).deliver
        end
        send_email(customer.email).deliver
      rescue Net::SMTPSyntaxError => e
        error_msg = "Newsletter sending failed on #{Time.now} with: #{e.message}. e.inspect: #{e.inspect}"
        logger.warn error_msg
        yield customer, nil
        next
      end
    end
  end
end

我想要实现的是每天早上都会发出时事通讯,如果 Rails/Sidekiq 遇到问题,它会简单地自行关闭,因此时事通讯不会影响主网站上的“生活”(它的服务器)。

提前感谢您的每一个建议。我在这个问题上被困了一段时间。

【问题讨论】:

    标签: ruby-on-rails ruby sidekiq newsletter


    【解决方案1】:

    我认为理想情况下,您应该将后台任务服务器与 Web 服务器分开,这样后台进程就不会影响 Web 服务器的性能。我在一家流量很大/负载很高的公司工作,我们这里有一种架构。

    这个答案中有关于如何停止重试的解释:Disable automatic retry with ActiveJob, used with Sidekiq

    另一件事,您的电子邮件发送是同步完成的(.deliver)。这意味着您的任务是一个拥有许多客户的庞大的单一流程,对内存产生巨大影响。相反,您可以使用 Deliver_later,这样每个客户都会得到它自己的小工人。这也将有助于缓解 CPU 和内存的使用。您甚至可以创建一个工作人员来为每个客户发送电子邮件,并使用您的单一作业来仅发送这些邮件。

    class NewslettertJob < ApplicationJob
      def perform
        ...
        customers.each |customer| do
          NewsletterMailer.morning_blast(customer, data).deliver_later if customer.email.present?
        end 
      end
    end
    

    但是,我认为灵丹妙药是将 Sidekiq 服务器与 Web 服务器分开 - 让一台服务器专门用于后台任务。在您的 Web 服务器上,您甚至不需要启动 sidekiq 实例。

    【讨论】:

    • 嗨@cesartalve,谢谢你的回答。我会考虑在单独的服务器上移动它。只是想知道 - 在rake 任务中,我在那里运行这个命令:NewslettertJob.perform_later.perform_later 部分在这里有意义吗?
    • 确实如此。您只是说应将作业放入队列中,而不是立即执行。
    【解决方案2】:
    1. 如果你的机器只有一个核心,Sidekiq 和 puma 会争夺 CPU。降低 Sidekiq 的并发性,使其使用更少的 CPU,或者获得具有多核的机器,或者将 Sidekiq 移动到另一台机器上。

    2. 如果 Sidekiq 进程正在使用 100% 的内核,请降低并发设置。 Sidekiq 6.0 中的默认值为 10,这是一个很好的默认值,但如果您只是发送电子邮件,您可能会将其增加到 20。如果您希望利用多个内核来更快地处理作业,您可以运行多个 Sidekiq 进程。

    【讨论】:

    • Mike Perham 是 sidekiq 的作者,所以这基本上是您将得到的答案专家
    猜你喜欢
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 2022-08-06
    • 1970-01-01
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多