listmonk 如何为百万级订阅者列表调大 Batch size 提升活动发送吞吐
【免费下载链接】listmonkHigh performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.项目地址: https://gitcode.com/GitHub_Trending/li/listmonk
当 listmonk 管理的列表达到数百万订阅者时,活动(campaign)发送的瓶颈往往不在 SMTP 通道,而在数据库往返:发送管道每个循环只会从数据库拉取一批订阅者,批次太小意味着更多次数据库查询。listmonk 提供了一个专门的Batch size参数来解决这个问题——官方文档明确说明它"在处理拥有百万级订阅者的超大列表时,用于最大化吞吐量"。这篇文章给出完整的调整路径:在管理后台或配置文件里修改app.batch_size、重启生效,然后从活动页面的进度变化确认发送在正常推进。
Batch size 到底控制什么
先看它的工作机制(来自 配置文档 的 Performance 章节):
The batch size parameter is useful when working with very large lists with millions of subscribers for maximising throughput. It is the number of subscribers that are fetched from the database sequentially in a single cycle (~5 seconds) when a campaign is running. Increasing the batch size uses more memory, but reduces the round trip to the database.
- 它是活动运行期间、单个循环(约 5 秒)内从数据库顺序取出的订阅者数量;
- 取批是游标式的:代码注释说明批次按 ID 排序,每一批取上一批最后一个 ID 之后的下一批(见 store 实现),每批拉取时把
BatchSize作为查询的 limit 传入(见 pipe 拉取逻辑); - 代价是内存:调大 Batch size 会占用更多内存,换来的是减少数据库往返次数。
相关参数在 schema 中的默认值(存于数据库的 settings 表,首次安装时写入):
('app.concurrency', '10'), ('app.message_rate', '10'), ('app.batch_size', '1000'),也就是说,默认 Batch size 是 1000,而并发 worker 数为 10、每 worker 每秒 10 条。
确定取值:先算出你的最大可达吞吐
Settings → Performance 页面 对app.batch_size输入框的官方说明(英文原文,见 i18n 文案):
The number of subscribers to pull from the database in a single iteration. Each iteration pulls subscribers from the database, sends messages to them, and then moves on to the next iteration to pull the next batch. This should ideally be higher than the maximum achievable throughput (concurrency * message_rate).
即:Batch size 理想上应大于最大可达吞吐 = concurrency × message_rate。例如默认 10 × 10 = 100 条/秒,那么 1000 的默认值已经留了 10 倍余量;如果你同时把concurrency和message_rate调大以吃满 SMTP 服务器的限额(message_rate 的官方说明就是让你结合 concurrency 把总发出速率控制在邮件服务器限额之下),Batch size 也要相应调大,否则每个循环取回的批次还没发完就要回库取下一批,吞吐被数据库往返卡住。
在管理后台修改(推荐路径)
- 登录后进入Settings → Performance标签页(页面实现见 performance.vue)。
- 找到Batch size输入框。UI 限制为最小 1、最大 100000,占位符显示默认值 1000。
- 按上一步算出的目标值填入(下面示例用 20000,请按自己的 concurrency × message_rate 与实际内存情况替换)。
- 保存该页设置。
保存只是把新值写进数据库的 settings。由于发送管理器是在进程启动时读取app.batch_size构建配置的(见 manager 初始化),改动需要重启 listmonk 才能影响发送管道。Docker 部署下按 配置文档 的做法重启:
sudo docker compose stop ; sudo docker compose up在配置文件里修改(适合用 TOML 管理配置的环境)
listmonk 的 TOML 配置项也可以用LISTMONK_前缀的环境变量提供(点号换成双下划线),并且除少数底层配置外,大部分设置都可以通过管理后台管理(见 配置文档)。两种方式任选其一:
方式一:生成并编辑配置文件。先运行listmonk --new-config生成一份样例配置,然后在[app]段加入:
[app] batch_size = 20000注意config.toml.sample本身没有包含batch_size这一行,需要自行添加;样例里的max_open = 25等[db]项保持原样。
方式二:环境变量。按文档中"periods replaced by__"的转换规则,app.batch_size对应:
LISTMONK_app__batch_size=20000改完同样重启进程。如果你的部署把--config指向了具体文件,也可以用--config config.toml多次传入多个 TOML 文件来分层管理。
验证:从活动进度确认新参数在生效
文档没有给出独立的健康检查命令,可用的观测方式是活动本身的状态与进度(见 活动列表页):
- 启动(或继续发送)一个面向大列表的活动,确认状态为Running;
- 活动详情中的进度显示为
sent / toSend并带进度条,sent持续增长说明取批和发送都正常; - 活动发完订阅者后状态变为Finished(代码在取不到新批次时结束活动,见 cleanup 逻辑)。
两个需要注意的边界:
- 内存:这是文档明确写出的代价——"Increasing the batch size uses more memory"。调大后应观察 listmonk 进程内存是否在机器承受范围内,UI 上限 100000 不是推荐值。
- SMTP 限速:Batch size 只影响取批速度,真正每秒发出去多少由
concurrency × message_rate决定,并受 SMTP 服务器限速约束。如果你的邮件服务器有总量窗口限制,Performance 页还有Message sliding window开关(限制给定时间段内发出的总消息数,超限的消息会暂停发送直到窗口释放),必要时配合使用。
顺带处理管理页面变慢的问题
百万级订阅者下还有另一个已知的性能问题,与发送吞吐无关但常被一并遇到:Performance 文档 指出,当数据库累积了大量订阅者、活动浏览和点击记录后,Dashboard 的聚合统计、Lists 页每个列表旁的订阅数、Subscribers 页的总数等计数操作会显著变慢(可能耗时几十秒)。文档建议在百万级安装中开启Settings → Performance → Cache slow database queries,让上述计数不再实时查询,而是按 crontab 表达式(默认0 3 * * *,即每天 3 点)定期更新缓存。这是该文档同时给出的配套优化项,如果你已经按本文调大了 Batch size 并运行大列表活动,管理页加载慢时可以一并打开。
【免费下载链接】listmonkHigh performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.项目地址: https://gitcode.com/GitHub_Trending/li/listmonk
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考