Richie
(Richie Rich)
1
我们有一个名为 #Announcements 的类别,我们所有的成员都会自动订阅以关注第一篇帖子。
这使我们能够按设定的时间/日期安排发布到该类别中的帖子。
然后,该公告将通过电子邮件发送给大约 25,000 名成员。
我们面临的问题是,电子邮件需要一个多小时才能发送,这对于时间关键的公告来说并不理想。
如果我关注 Sidekiq,我可以看到“Scheduled”(已安排)计数器逐个累加所有单独的电子邮件,当它达到大约 20,000 封时,它会将它们移至“Enqueued”(已排队)选项卡,然后它们最终开始发送。
我能加快这个过程吗? 
对于时间关键的电子邮件,希望它们发送速度比现在快大约 100 倍 
此讨论可能对您有帮助,因为它解释了如何设置 DISCOURSE_MAX_DIGESTS_ENQUEUED_PER_30_MINS_PER_SITE,该设置定义了摘要的全局限制。
2 个赞
Richie
(Richie Rich)
3
我今晚计时了。
我安排了一个帖子在 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 封的速率更快地发送这些电子邮件。
Richie
(Richie Rich)
5
也许?
我真的不知道 
服务器上的 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 个赞
Richie
(Richie Rich)
11
很棒的见解,谢谢 
DISCOURSE_SIDEKIQ_WORKERS 必须是 5 的倍数吗?我可以将其设置为 7 吗?
我的 app.yml 中没有这个参数设置,所以我假设它在某个地方默认为 5。
我可以将此设置创建在现有的 unicorn 工作进程设置下,然后重建吗?
例如:
expose:
- “443:443”
env:
UNICORN_WORKERS: 8
DISCOURSE_SIDEKIQ_WORKERS: 7
就这么简单吗? 
Richie
(Richie Rich)
12
是否有人能确认,当 DISCOURSE_SIDEKIQ_WORKERS 参数目前不存在时,这是对我的 app.yml 所做的正确更改?
1 个赞
Richie
(Richie Rich)
14
是的,这是正确的。
任何(大多数?)设置都可以通过这种方式覆盖。默认值来自 discourse_defaults.conf。
2 个赞
Richie
(Richie Rich)
16
感谢 @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
我将在本周晚些时候重建并计时发送邮件 
只是为了让我知道我的更改已生效,我是否可以认为这个 Threads 值应该从 5 增加到 7?
2 个赞
Richie
(Richie Rich)
19
感谢您的跟进。
可惜不是。
我已经将线程数从 5 增加到 8,但电子邮件从头到尾发送仍然需要将近一个小时。
我预计总吞吐量可能会增加 40%。
当作业排队时,您是否看到 7/7 的利用率?
另外,看看它在处理作业时的服务器负载,如果可以的话,我建议进一步提高。
Richie
(Richie Rich)
21
哦哦哦,等一下。Discourse 是否在某种程度上限制了它自己?
我是否错过了限制其 CPU 使用率的设置?? 
它本身并没有限制,但每个 sidekiq 工作进程一次只能处理一个作业,所以如果你有 22000 封电子邮件等待发送,其中七封将同时处理。
从荒谬的一面来看,如果你设置了 1000 个并行工作进程,服务器可能无法跟上。因此,关键在于找到一个适合你所有需求的数字:
- 同时处理尽可能多的作业,以便更快地发送 22000 封电子邮件
- 但不要占用所有服务器资源,以免给网站用户留下任何资源
2 个赞