感谢 @Falco
我主要困惑的是,在配置相同的情况下,为何性能会在大约一周内波动,从每天完成约 1100 万个任务到仅约 30 万个任务。按每秒处理的任务数计算,速度差异高达约 35 倍。
CPU 使用率目前已回落至约 15-20%,这与平时水平一致。但处理任务的速度依然很慢。
为澄清并确认一下,我的意思是分配(而非添加)一些 Sidekiq 进程专门处理低优先级队列,因为低优先级任务似乎能以更快的速度处理,且可能不会受到相同的瓶颈影响。我推测这可能解释了为何每秒处理的任务数会出现如此巨大的波动(即低优先级的“简单”任务被卡在默认队列的积压之后)。
再澄清一下:您认为 PostgreSQL 的性能问题是导致任务完成缓慢的原因,还是仅仅导致了昨天我注意到的 CPU 使用率飙升事件(该问题现已恢复正常)?
是的,正确 @Stephen - NVMe SSD RAID 1。
更新:我尝试了几次删除低优先级队列和默认队列,但对速度没有影响,因为默认队列会立即再次增长。随后,我尝试删除默认队列并启用只读模式。这使每秒处理的任务数急剧飙升,低优先级队列的处理速度达到了原来的约 100 倍。
编辑:看起来即使只有一个较大的低优先级队列,处理速度仍然很慢。如果我将 Discourse 设置为只读模式,然后清空低优先级和默认优先级队列,后续的任务处理速度会保持极快,持续清空计划任务和队列,直到我禁用只读模式。
bartv
(Bart )
2020 年2 月 12 日 07:43
25
我的下一步是进入 Discourse 应用,运行 htop 或 top 命令,查看 CPU 占用最高的进程,从而确定具体是哪个进程导致了问题。
pfaffman
(Jay Pfaffman)
2020 年2 月 12 日 11:15
26
这听起来像是 PostgreSQL 成了瓶颈。你可以配置 Prometheus 来跟踪其性能,看看它是否获得了足够的内存。
感谢您的反馈 @pfaffman 我认为 app.yml 中的 db_shared_buffers 和 db_work_mem 是控制 PostgreSQL 内存访问的唯一选项,对吗?
我已经尝试过将这两个值调高和调低。当前 app.yml 中的设置如下:
db_shared_buffers: “32768MB”
db_work_mem: “128MB”
系统总内存为 128GB。
我还尝试修改 /var/discourse/shared/standalone/postgres_data/postgresql.conf 中的 max_connections 参数,然后重新构建 Discourse。测试了高于默认值(100)的数值,范围从 200 到 500。当前设置为 300。不过,我不确定这样修改是否真的生效了。
我在 /var/discourse/templates/postgres.template.yml 中看到了以下配置:
db_synchronous_commit: “off”
db_shared_buffers: “256MB”
db_work_mem: “10MB”
db_default_text_search_config: “pg_catalog.english”
db_name: discourse
db_user: discourse
db_wal_level: minimal
db_max_wal_senders: 0
db_checkpoint_segments: 6
db_logging_collector: off
db_log_min_duration_statement: 100
感谢 @bartv ,按照您的建议,我通过 top 命令在 Discourse 应用内部进行了监控。我发现由 postgres 用户运行的 postmaster 进程数量相当多,CPU 使用率波动较大。截图展示了在较长时间内具有相似使用统计的情况。
使用约 95% 的 32 个核心:
使用约 20%,postmaster 的 CPU 使用率较低。
使用约 6% 的 CPU,此时只读模式处于激活状态。
pfaffman
(Jay Pfaffman)
2020 年2 月 12 日 14:12
29
您的数据库有多大?您有多少用户?每天有多少新帖子?
您应该首先从 PostgreSQL 控制台运行 VACUUM ANALYZE;。
这可能需要一些时间;您可能希望暂时停止 Sidekiq,以减轻其运行时的负载。
如果这没有帮助,我们应该启用 pg_stat_statements,然后检查哪些查询占用了大量 CPU 资源。
pfaffman
(Jay Pfaffman)
2020 年2 月 12 日 15:28
32
哦,这可不简单。
你应该了解一下 PostgreSQL 的性能调优。这种性能水平已经超出了这里常见的自托管范畴。
我建议给 PostgreSQL 分配大约四分之三的内存。我肯定会将数据容器和 Web 容器分开。但你可能需要更复杂的 PostgreSQL 配置才能达到所需的性能。
编辑:不过我并没有处理过更大规模数据库的经验,所以请参考下文!
我们使用更少的内存和更少的 CPU 资源,就能处理规模大得多的数据库。
pg_stat_statements 的信息很可能能告诉我们问题出在哪里。
非常感谢各位的帮助。
所以我尝试运行了 VACUUM ANALYZE;,但不幸的是没有效果。以下是使用的命令,供参考:
cd /var/discourse/
./launcher enter app
sudo -u postgres psql
\c discourse
VACUUM ANALYZE;
我尝试启用 pg_stat_statements,步骤如下:
在以下位置添加/修改了相关行:/var/discourse/shared/standalone/postgres_data/postgresql.conf
shared_preload_libraries = ‘pg_stat_statements’ # (需要重启才能生效)
pg_stat_statements.max = 10000
pg_stat_statements.track = all
pg_stat_statements.track_utility = on
pg_stat_statements.save = off
然后重新构建 Discourse 并运行:
./launcher enter app
sudo -u postgres psql
\c discourse
CREATE EXTENSION pg_stat_statements;
我尝试执行查询,但收到了以下错误:
ERROR: pg_stat_statements 必须通过 shared_preload_libraries 加载
我猜测是我对 postgresql.conf 文件(/var/discourse/shared/standalone/postgres_data/postgresql.conf)的修改没有生效(我在修改后重新构建了 Discourse)。是否可以通过 app.yml 文件进行这些修改?或者您是否发现我哪里做错了?
pfaffman
(Jay Pfaffman)
2020 年2 月 16 日 16:45
35
重新构建 Discourse 会清除这些更改。重启容器可能就能解决问题。(在容器内执行类似 sv restart postgres 的命令也可能有效)。
pfaffman:
sv restart postgres
谢谢,我尝试重启了容器:
./launcher stop app
./launcher start app
但在尝试查询时仍然收到相同的错误:
ERROR: pg_stat_statements must be loaded via shared_preload_libraries
我之前所做的更改即使在重建后仍保留在此文件中:
/var/discourse/shared/standalone/postgres_data/postgresql.conf
我怀疑这个文件并不是我应该进行这些编辑的地方:face_with_monocle:
也许是因为在 containers 文件夹中只使用了 app.yml(和 mail-receiver.yml),尚未实施使用 data.yml。
pfaffman
(Jay Pfaffman)
2020 年2 月 17 日 12:38
37
markersocial:
我怀疑这个文件并不是我应该进行这些编辑的地方
虽然未经实际查看,但很可能是在容器内的 /etc/postgres 目录下。你可能还需要安装它所要求的任何库。
谢谢,这起初帮了大忙。 问题似乎已解决,只需增加 postgresql.conf 中的最大连接数,任务队列的处理速度就大幅提升。但不幸的是,大约一天后速度又慢了下来。
以下是操作步骤,如果对其他想要增加 PostgreSQL max_connections 的用户有帮助,可以参考:
docker ps
获取容器 ID,例如 aaabbbccc123,并在以下命令中替换该 ID:
将 postgresql.conf 文件从 Docker 容器内复制到本地文件系统:
docker cp aaabbbccc123:/etc/postgresql/10/main/postgresql.conf /srv
编辑配置文件:
nano /srv/postgresql.conf
将其复制回 Docker 容器:
docker cp /srv/postgresql.conf aaabbbccc123:/etc/postgresql/10/main/postgresql.conf
cd /var/discourse
./launcher stop app
./launcher start app
删除残留文件(可选):
rm /srv/postgresql.conf
@supermathie I believe I’ve successfully enabled pg_stat_statements
I tried using this query:
SELECT
(total_time / 1000 / 60) as total,
(total_time/calls) as avg,
query
FROM pg_stat_statements
ORDER BY 1 DESC
LIMIT 100;
From this guide: The most useful Postgres extension: pg_stat_statements
I can’t really read the result though, I think I’ve done something wrong.
total | avg | query
1671.1110420745 | 374.736186677194 | SELECT COUNT(*) FROM ( +
| | SELECT $1 FROM +
| | notifications n +
| | LEFT JOIN topics t ON t.id = n.topic_id +
| | WHERE t.deleted_at IS NULL AND +
| | n.notification_type <> $2 AND +
| | n.user_id = $3 AND +
| | n.id > $4 AND
pfaffman
(Jay Pfaffman)
2020 年2 月 19 日 13:39
40
现在,既然你已经知道想要做什么,你就可以在 app.yml 中使用 replace 部分来做出这些更改。
另外,你也可以直接运行 ./launcher enter app 并编辑文件。但请注意,当你重新构建时,这些更改不会出现在新的容器中。