Rails - Как предотвратить замедление работы сервера Sidekiq?

У меня есть информационный бюллетень, который я отправляю своим клиентам (~ 10 тыс. Писем) каждое утро, и иногда случается, что это задание Sidekiq требует большой производительности процессора / памяти, что веб-сайт (приложение 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 столкнется с проблемой, он просто отключится, поэтому информационный бюллетень не повлияет на «жизнь» на основном веб-сайте (его сервере).

Заранее благодарю за каждый совет. Я уже какое-то время зацикливаюсь на этом вопросе.


person user984621    schedule 20.03.2020    source источник


Ответы (2)


Я думаю, что в идеале вам следует отделить серверы фоновых задач от веб-серверов, чтобы фоновый процесс не влиял на производительность веб-сервера. Я работаю в компании с очень высоким трафиком / высокой нагрузкой, и у нас здесь своего рода архитектура.

В этом ответе есть объяснения того, как остановить повторные попытки: Отключить автоматическую повторную попытку с помощью ActiveJob, используется с Sidekiq

Другое дело, ваша электронная почта отправляется синхронно (.deliver). Это означает, что ваша задача представляет собой огромный монолитный процесс с множеством клиентов, оказывающий огромное влияние на память. Вместо этого вы можете использовать delivery_later, чтобы каждый покупатель получал своего маленького работника. Это также поможет снизить использование ЦП и памяти. Вы даже можете создать воркера для отправки электронных писем каждому клиенту и использовать свое монолитное задание для их отправки.

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

Однако я думаю, что серебряная пуля отделяет ваш сервер sidekiq от вашего веб-сервера - наличие одного сервера, выделенного для фоновых задач. На своем веб-сервере вы даже не запускаете экземпляры sidekiq.

person cesartalves    schedule 20.03.2020
comment
Привет, @cesartalves, спасибо за ответ. Я буду искать возможность перенести его на отдельный сервер. Просто интересно - в задаче rake запускаю там такую ​​команду: NewslettertJob.perform_later. Имеет ли здесь смысл часть .perform_later? - person user984621; 20.03.2020
comment
Оно делает. Вы просто говорите, что задание должно быть поставлено в очередь, а не выполняться сразу. - person cesartalves; 20.03.2020

  1. Если у вашей машины только одно ядро, Sidekiq и puma будут бороться за процессор. Уменьшите параллелизм Sidekiq, чтобы он использовал меньше ЦП, или получите машину с несколькими ядрами, или переместите Sidekiq на другую машину.

  2. Если процесс Sidekiq использует 100% ядра, уменьшите параметр параллелизма. По умолчанию в Sidekiq 6.0 установлено 10, что является хорошим значением по умолчанию, но если вы просто доставляете электронные письма, вы, вероятно, можете увеличить его до 20. Вы можете запустить несколько процессов Sidekiq, если хотите использовать несколько ядер для более быстрой обработки заданий.

person Mike Perham    schedule 20.03.2020
comment
Майк Перхам - автор sidekiq, так что это в основном эксперт в ответах, которые вы получите. - person cesartalves; 21.03.2020