Есть ли способ отправлять уведомления по электронной почте быстрее?

У нас есть категория #Announcements, на которую все наши участники автоматически подписаны для отслеживания первого поста.

Это позволяет нам планировать публикацию постов в этой категории в определённое время или дату.

В свою очередь, объявление затем рассылается по электронной почте примерно 25 тысячам участников.

Проблема, с которой мы сталкиваемся, заключается в том, что отправка писем занимает более часа, что не идеально для срочных объявлений.

Если я наблюдаю за Sidekiq, то вижу, как счётчик «Scheduled» (Планируемые) по одному накапливает все отдельные письма; когда их количество достигает примерно 20 000, они перемещаются во вкладку «Enqueued» (В очереди), и только после этого начинают отправляться.

Могу ли я как-то ускорить этот процесс? :thinking:

Для срочных писем было бы здорово отправлять их примерно в 100 раз быстрее, чем сейчас :blush:

Эта дискуссия может вам помочь, так как в ней объясняется, как установить DISCOURSE_MAX_DIGESTS_ENQUEUED_PER_30_MINS_PER_SITE, который определяет глобальный лимит для дайджестов.

Я засёк время сегодня вечером.

Я запланировал публикацию поста в категории #Announcements на 18:30.


В 18:40 в очереди Scheduled находилось 15 000 писем.


В 18:45, то есть через 15 минут после публикации поста, в очереди Scheduled было уже 22 000 писем.


В 18:48 эти письма начали постепенно перемещаться в очередь Enqueued:


В 18:51 они всё ещё перемещались:


В 19:03 письма уже были в пути к получателям:


К 19:10 осталось только 10 000 писем:


В 19:27 осталось всего 569 писем:


А в 19:29 все письма были отправлены:


Итак, у нас есть полный час на отправку 22 000 уведомлений по электронной почте.

Может ли кто-нибудь помочь мне определить узкое место в этом процессе?

Мне очень хотелось бы иметь возможность отправлять эти письма быстрее, чем текущая скорость в 22 000 писем в час.

Спонтанно,
Не может ли это быть проблемой нагрузки на инфраструктуру?

Возможно?

Честно говоря, я не знаю :person_shrugging:

Загрузка процессора на сервере достигла примерно 44%:

А для SMTP я использую AWS SES.

Здесь происходит две вещи:

  • задержка при постановке задач отправки писем в очередь
  • время обработки фактической отправки письма

По первому пункту я не на 100% уверен, но, думаю, уменьшение значения email_time_window_mins приводит к более раннему помещению уведомлений в очередь.

После того как задачи отправки писем помечены как scheduled, ваши воркеры Sidekiq обрабатывают их по одной. Увеличение количества воркеров Sidekiq (поднимите DISCOURSE_SIDEKIQ_WORKERS с 5 до 10, 15 или 20 в зависимости от мощности сервера) означает, что больше задач обрабатывается одновременно, поэтому очередь очищается в 2/3/4 раза быстрее.

Я не знаю тонкостей работы бэкенда, но параметр email_time_window_mins — это просто задержка перед отправкой первого письма. В течение этого времени любой пользователь, которому предназначено письмо, может «потерять» его, если окажется активным в течение этого окна (официальный термин: письмо пропущено; причина пропуска: пользователь был замечен недавно).

Задержка по умолчанию составляет 10 минут, то есть пост должен быть опубликован в течение 10 минут, и только после этого будут отправлены письма.

Проблема Ричи связана с разницей во времени между отправкой первого и последнего письма — задержка в один час. Вероятно, это обусловлено огромным количеством писем, которые необходимо отправить, хотя я не могу утверждать это наверняка.

Изменение вышеуказанного параметра ускорит отправку только первого письма, но не сократит время завершения отправки всей партии из 22 000 писем.


Какое значение рекомендуется установить, учитывая, что это зависит от возможностей инфраструктуры?

Может ли высокое значение привести к проблемам с сервером, например, из-за нагрузки или по другим причинам?

«Столько, сколько сервер может выдержать».

Это на 100% зависит от мощности сервера автора оригинального поста (OP): слишком много — и всё замедлится, слишком мало — и обработка займёт больше времени.

Учитывая, что график нагрузки на ЦП достигает 40% (это загрузка одного процессора или общая ёмкость?), я бы, вероятно, начал с увеличения значения в 2 раза (консервативный подход) или в 3 раза (агрессивный подход) и посмотрел, что произойдёт, в зависимости от готовности к риску замедления работы.

Отличное наблюдение, спасибо :slight_smile:

Должно ли значение DISCOURSE_SIDEKIQ_WORKERS быть кратным 5? Например, могу ли я установить его равным 7?

У меня в app.yml нет этой настройки, поэтому предполагаю, что по умолчанию она равна 5.

Могу ли я просто добавить эту настройку под существующим параметром UNICORN_WORKERS и затем пересобрать?

Например:

expose:
  - "443:443"

env:
    UNICORN_WORKERS: 8
    DISCOURSE_SIDEKIQ_WORKERS: 7

Всё так просто? :thinking:

Может ли кто-нибудь подтвердить, что это правильное изменение для моего файла app.yml, если параметр DISCOURSE_SIDEKIQ_WORKERS в настоящее время отсутствует?

Я думаю, что да, после краткого запроса к боту ИИ.

Спасибо, @TempAccount

Интересно, что DISCOURSE_SIDEKIQ_WORKERS встречается всего одиннадцать раз на всём сайте meta:

https://meta.discourse.org/search?q=%22DISCOURSE_SIDEKIQ_WORKERS%22%20order%3Alatest_topic

…и один из этих случаев — в этой теме :flushed_face:

Да, это верно.

Любое (большинство?) настроек можно переопределить таким образом. Значение по умолчанию берётся из discourse_defaults.conf.

Спасибо, @supermathie

Теперь мой app.yml выглядит так:

env:
  LANG: en_US.UTF-8
  # DISCOURSE_DEFAULT_LOCALE: en

  ## Сколько одновременных веб-запросов поддерживается? Зависит от памяти и ядер CPU.
  ## Будет установлено автоматически при загрузке на основе обнаруженных процессоров, либо вы можете переопределить
  UNICORN_WORKERS: 8

  ## Добавил эту строку 04/10/25
  ## ССЫЛКА: https://meta.discourse.org/t/is-there-a-way-i-can-send-email-notifications-faster/383103/12
  DISCOURSE_SIDEKIQ_WORKERS: 7

Позже на этой неделе я пересоберу систему и замерю время отправки писем :smiley:

Просто чтобы убедиться, что мои изменения вступили в силу, правильно ли я понимаю, что значение Threads должно увеличиться с 5 до 7?

Да, подтверждено:

@Richie, вам удалось решить вашу проблему?

Спасибо за уточнение.

К сожалению, нет.

Я увеличил количество потоков с 5 до 8, но отправка писем по-прежнему занимает почти час от начала до конца.

Я ожидаю, возможно, 40% прироста общей пропускной способности.

Когда задачи находятся в очереди, видите ли вы загрузку 7/7?

Также проверьте нагрузку на сервер во время их обработки, и если вы сможете её ещё больше повысить, я рекомендую сделать это.

О-о-о, погодите минутку. Не ограничивает ли сам Discourse свои ресурсы?

Не упустил ли я настройку, которая ограничивает использование CPU? :scream:

Сам по себе Discourse не ограничивает себя, но каждый воркер Sidekiq обрабатывает только одну задачу за раз. Таким образом, если у вас 22 000 писем, ожидающих отправки, одновременно будет обрабатываться только семь из них.

Если же зайти в крайности, сервер, вероятно, не справится, если установить количество параллельных воркеров на 1000. Поэтому задача заключается в подборе числа, которое удовлетворяет всем вашим потребностям:

  • обрабатывать как можно больше задач одновременно, чтобы быстрее отправить 22 000 писем;
  • но при этом не занимать все ресурсы сервера, чтобы для пользователей сайта оставались необходимые ресурсы.