有没有办法可以更快地发送电子邮件通知?

我们有一个名为 #Announcements 的类别,我们所有的成员都会自动订阅以关注第一篇帖子。

这使我们能够按设定的时间/日期安排发布到该类别中的帖子。

然后,该公告将通过电子邮件发送给大约 25,000 名成员。

我们面临的问题是,电子邮件需要一个多小时才能发送,这对于时间关键的公告来说并不理想。

如果我关注 Sidekiq,我可以看到“Scheduled”(已安排)计数器逐个累加所有单独的电子邮件,当它达到大约 20,000 封时,它会将它们移至“Enqueued”(已排队)选项卡,然后它们最终开始发送。

我能加快这个过程吗? :thinking:

对于时间关键的电子邮件,希望它们发送速度比现在快大约 100 倍 :blush:

此讨论可能对您有帮助,因为它解释了如何设置 DISCOURSE_MAX_DIGESTS_ENQUEUED_PER_30_MINS_PER_SITE,该设置定义了摘要的全局限制。

2 个赞

我今晚计时了。

我安排了一个帖子在 18:30 发布到 #Announcements 类别。


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 封电子邮件:


21:29 时,所有电子邮件均已发送完毕:


所以,发送 22,000 封电子邮件通知需要整整一个小时。

有人能帮我找出瓶颈在哪里吗?

我非常希望能够比目前每小时 22,000 封的速率更快地发送这些电子邮件。

凭直觉判断,
这会不会是基础设施负载问题?

1 个赞

也许?

我真的不知道 :person_shrugging:
服务器上的 CPU 使用率飙升至约 44%:

我使用 AWS SES 作为 SMTP。

这里有两个问题:

  • 电子邮件作业入队时的延迟
  • 发送实际电子邮件的处理时间

对于第一个问题,我不太确定,但我认为降低 email_time_window_mins 会使通知更快地入队。

一旦电子邮件作业被“调度”,您的 sidekiq 工作进程会一次处理一个。增加 sidekiq 工作进程(将 DISCOURSE_SIDEKIQ_WORKERS 从 5 提高到 10、15 或 20,具体取决于服务器容量)意味着更多作业同时处理,因此队列的清空速度会快 2 倍/3 倍/4 倍。

4 个赞

我不知道后端工作的最精细细节,但 email_time_window_mins 只是第一个电子邮件发出之前的延迟设置。在此期间,任何设置为接收电子邮件的用户都可能“放弃”电子邮件,如果他们恰好在该时间窗口内处于活动状态(官方术语:电子邮件已跳过;跳过原因:用户最近被看到)。

默认延迟为 10 分钟,这意味着帖子必须在线 10 分钟,然后才会发送电子邮件。

Richie 的问题是第一封电子邮件和最后一封电子邮件之间的时间差……延迟一个小时。这可能是由于需要发送的大量电子邮件造成的,尽管我也不能确定。

更改上述设置只会加快第一封电子邮件的发送速度,但不能解决 22,000 封电子邮件整个批次的完成持续时间。


根据基础设施能力,推荐的设置是什么?

高设置是否会导致服务器在负载或其他方面出现问题?

1 个赞

“服务器能处理多少就设置多少”。

这 100% 取决于 OP 的服务器容量——太多会拖慢速度,太少则处理时间更长。

考虑到 CPU 图表达到 40%(这是一个 CPU 的还是总容量的?),我可能会先尝试增加 2 倍(保守)或 3 倍(激进),然后根据对减速的风险承受能力看看会发生什么。

1 个赞

很棒的见解,谢谢 :slight_smile:

DISCOURSE_SIDEKIQ_WORKERS 必须是 5 的倍数吗?我可以将其设置为 7 吗?

我的 app.yml 中没有这个参数设置,所以我假设它在某个地方默认为 5。

我可以将此设置创建在现有的 unicorn 工作进程设置下,然后重建吗?

例如:

expose:
  - “443:443”

env:
    UNICORN_WORKERS: 8
    DISCOURSE_SIDEKIQ_WORKERS: 7

就这么简单吗? :thinking:

是否有人能确认,当 DISCOURSE_SIDEKIQ_WORKERS 参数目前不存在时,这是对我的 app.yml 所做的正确更改?

1 个赞

我相信是的,通过向 AI 机器人进行简短的询问。

1 个赞

感谢 @TempAccount

有趣的是,DISCOURSE_SIDEKIQ_WORKERS 在整个 meta 中只出现了 十一次

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

……其中一次就在这个帖子里 :flushed_face:

是的,这是正确的。

任何(大多数?)设置都可以通过这种方式覆盖。默认值来自 discourse_defaults.conf

2 个赞

感谢 @supermathie

我的 app.yml 现在内容如下:

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

  ## 支持多少并发 Web 请求?取决于内存和 CPU 核心。
  ## 将由 bootstrap 根据检测到的 CPU 自动设置,或者您可以覆盖它
  UNICORN_WORKERS: 8

  ## 于 2025/10/04 添加此行
  ## 参考: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

2 个赞

是的,已确认:

2 个赞

@Richie 你能解决你的问题吗?

感谢您的跟进。

可惜不是。

我已经将线程数从 5 增加到 8,但电子邮件从头到尾发送仍然需要将近一个小时。

我预计总吞吐量可能会增加 40%。

当作业排队时,您是否看到 7/7 的利用率?

另外,看看它在处理作业时的服务器负载,如果可以的话,我建议进一步提高。

哦哦哦,等一下。Discourse 是否在某种程度上限制了它自己?

我是否错过了限制其 CPU 使用率的设置?? :scream:

它本身并没有限制,但每个 sidekiq 工作进程一次只能处理一个作业,所以如果你有 22000 封电子邮件等待发送,其中七封将同时处理。

从荒谬的一面来看,如果你设置了 1000 个并行工作进程,服务器可能无法跟上。因此,关键在于找到一个适合你所有需求的数字:

  • 同时处理尽可能多的作业,以便更快地发送 22000 封电子邮件
  • 但不要占用所有服务器资源,以免给网站用户留下任何资源
2 个赞