备份期间磁盘使用率飙升,Discourse 严重崩溃 :-(

今天早上大约 5:35,我的论坛磁盘使用量突然激增并导致崩溃,完全离线。我不得不调整 Digital Ocean 镜像的大小才能使其恢复运行。唉。

以下是过去 24 小时的磁盘使用情况:

问题:我可以查看哪些日志或事后分析来弄清楚到底发生了什么?! 我检查了 Discourse 控制面板中的日志,但那里没有任何线索……日志在站点崩溃时戛然而止,随后在站点重新上线时又立即恢复。

1 个赞

我会先从找出是哪个目录导致问题开始。我的标准做法是进入 /var/discourse 目录,然后运行 du -h -d 1 命令。进入占用空间最大的目录,重复此过程,直到找到可疑目录。一旦找到,这可能会为你提供线索,帮助你了解问题所在。

3 个赞

也许可以自动备份?

3 个赞

是的,备份通常是这类故障的常见原因——过去 7 天的磁盘使用情况如何?

另外请注意,本地上传 也包含在这些备份中,因此如果你在 18:00 左右上传量显著增加,也会导致备份归档体积增大。

5 个赞

嗯。我一直在将文件从 S3 迁移回本地服务器,但该过程似乎是实时运行的,每次只能处理几百张图片(每张约 300KB),即每批约 0.1 GB。在过去的一周里,我可能运行了该脚本 20 次,因此 20 批总共占用了约 2 GB 的磁盘空间。我的磁盘空间原本非常充足。

有没有可能,尽管脚本看起来是实时迁移这些文件(从 S3 下载并立即上传到 Digital Ocean),但仍然存在某种队列作业的延迟,这些作业在凌晨 5:30 被触发,与图片迁移有关?

(另外:我手动运行这些批次直到晚上 9 点,所以据我所知,从晚上 9 点到凌晨 5:30 服务器崩溃前,服务器一直在进行正常操作。)

以下是我过去 7 天的磁盘使用情况。由于正在导入图片,磁盘使用量一直在稳步上升,但你可以看到它在凌晨 5:30 突然飙升至 100%:

除了我在“日志”选项卡中看到的日志文件外,是否还有其他日志文件可能提供关于凌晨 5:35 发生什么的线索?

1 个赞

嗯。我的备份设置为每两天上传到 S3,但从 9 号之后就没有任何记录了?

Discourse 的“备份”视图

Amazon S3 视图

顺便提一下,看到上述情况后,我点击了 Discourse 中的按钮手动触发备份。整个过程耗时 28 分钟,看起来一切正常;现在我在 Discourse 和 Amazon S3 的备份视图中都能看到那个 .tar.gz 文件了。那么,为什么自动备份没有触发呢?!啊啊啊啊。

我很困惑……这些目录的占用空间都不算特别大:

root@x-app:/var/www/discourse# du -h -d 1

3.5M	./lib
104K	./bin
8.0K	./.tx
148M    ./public
8.0K	./.bundle
14M     ./plugins
4.3M	./db
4.0K	./log
532M	./tmp
8.9M	./spec
17M     ./config
556M	./vendor
8.0K	./images
329M	./.git
2.0M	./script
80K	    ./docs
2.5M	./test
16K	    ./.github
17M	    ./app
1.6G	.

即使查看 Docker 容器内的整体磁盘空间,也没有之前那么大。我之前使用的是一个 80 GB 的 DigitalOcean Droplet,就是它达到了 100% 的使用率。于是我将其扩容至 160 GB,翻了一倍。理论上,这意味着其中一个目录的占用应该达到 50%,对吗?

root@x-app:/var/www/discourse# df -h

Filesystem      Size  Used Avail Use% Mounted on
overlay         155G   58G   98G  38% /
tmpfs            64M     0   64M   0% /dev
tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
shm             512M  2.6M  510M   1% /dev/shm
/dev/vda1       155G   58G   98G  38% /shared
tmpfs           3.9G     0  3.9G   0% /proc/acpi
tmpfs           3.9G     0  3.9G   0% /proc/scsi
tmpfs           3.9G     0  3.9G   0% /sys/firmware

你之前几乎每晚磁盘使用率都会接近 100%——看起来这次刚好成了压垮骆驼的最后一根稻草。我推测之前的备份失败是因为在创建要发送到 S3 的本地备份文件时磁盘空间不足,但只是失败了,并没有导致你的论坛崩溃。你最终注意到问题,是因为磁盘空间不足恰好在关键时刻让 PostgreSQL(或 Redis,或其他组件,这其实并不重要)无法正常工作,从而导致你的论坛宕机。

(我的服务器上有近 100GB 的图片。我执行 Discourse 的定时备份时不包含上传文件,但包含缩略图。然后,我会先对备份目录进行异地基于文件的增量备份,再对上传目录进行同样的操作。我已经测试过这种恢复方式,去年正是基于它完成了站点迁移。每晚存储 100GB 的 tar 压缩包显然是不现实的。)

7 个赞

啊哈,原来那些小尖峰是 Discourse 正在尝试创建备份!这下就说得通了。

那么,这是我过去 7 天的图表:

也许我们看到的情况是:

  1. 在过去的一周里,Discourse 多次尝试创建备份。这个过程会暂时占用大量磁盘空间,而每次尝试时,由于空间不足,备份都未能成功完成。

  2. 昨晚它再次尝试创建备份时,进度更靠前了一些,但不幸的是导致网站崩溃了。

这听起来很有道理,因为上一次成功的备份是在 7 月 9 日。因此,它等待了 2 天(根据我的设置),然后在 7 月 11 日再次尝试。那次失败了,于是它又等待了 24 小时,分别在 12 日、13 日以及 14 日进行了致命的那次重试。

如果情况确实如此,我希望 Discourse 能:

  1. 在备份失败时提供更明确的通知;

  2. 或许,如果 Discourse 在开始备份时发现可用磁盘空间低于某个百分比(例如 10%),就应自动“中止”备份(并生成通知),这样在磁盘空间已经紧张时,它甚至不会开始备份。

顺便一提,如果这真的是发生的情况,那么查看 7 月 11 日第一次失败的备份记录会发现,当时还有约 40% 的可用磁盘空间(大约 32GB!!!),但这仍不足以让备份成功完成。这是真的吗?!为什么 Discourse 在生成备份时需要如此大量的临时/工作空间?

2 个赞

昨晚它未必取得了进一步的进展;你只是“输掉了一场比赛”——当空间耗尽时会发生什么,取决于哪个组件首先受到问题的影响。

如果它无法进行备份,我倾向于认为它可能会尝试发送消息,但如果磁盘空间已满,它可能无法成功。:scream:

一个固定的百分比并不能说明太多问题;与上传内容相比,数据库可能非常小,反之亦然,而且是否包含缩略图、是否包含上传内容等因素也会影响结果。我想,或许可以设置一个可配置的空闲空间要求,以便你根据自己的网站进行调整。

我不清楚你是如何判断“过分”的——在我看来,这并不算过分。

2 个赞

说得对;正如你指出的,这里有很多变量在起作用。

哦,理论上“正确”的做法应该是计算备份等所需的空间量,等等。但为了保持超级简单,是的,就用一个固定的百分比就好。我只是在想……如果两个选择是“你的站点可能会完全崩溃并离线”或者“这是一个不完美但快速的解决方案”,那我当然选择后者,谢谢。:wink:

说到感谢,也要谢谢你一直以来在迁移工作以及对此事的建议上给予的帮助。:+1:t2:

1 个赞

估算备份所需空间是计算机科学中的难题之一……它和进度条算是远亲。:wink:

说正经的,备份的一部分是数据库转储,而很难提前估算其大小。如果你的图片多到空间成为问题,将它们纳入备份存档可能已超出主流做法。

通常情况下,在系统管理方面,可用空间监控和备份健康检查一直是运维负担,而非应用本身的负担。这也是大家付费让 CDCK 托管 Discourse 的原因之一。

还有很多其他情况会导致空间耗尽。我知道你关注的是那个让你中招的问题,但问题其实更为普遍,我认为这通常应作为运维开销来处理。

4 个赞

虽然我不想泼冷水,但根据帖子内容,实际上并没有确凿证据表明 Discourse 备份流程是导致该问题的原因。

为什么不 100% 确认这个问题确实是由每日备份流程引起的呢?主机上运行的每日 crontab 任务不止一个。

@pnoeric 是否对 /var/discourse 文件系统(容器外部)执行了 du 命令?

在您的笔记中,@pnoeric 写道:

root@x-app:/var/www/discourse# du -h -d 1

但这完全遗漏了包含所有备份和上传内容的 Discourse 共享目录!同时也遗漏了主机上的所有 Docker 文件(以及镜像)(如果长时间不修剪镜像,这些文件可能会变得很大)。

执行此检查的正确位置是在容器外部(而不是在容器内部):

例如(在容器外部):

cd /var/discourse 
/var/discourse# du -sh *
4.0K	bin
4.0K	cids
56K	containers
12K	discourse-doctor
24K	discourse-setup
164K	image
24K	launcher
4.0K	LICENSE
12K	README.md
24K	samples
8.0K	scripts
62G	shared
148K	templates

您看,在这台主机上,shared 目录大小为 62G

以及从文件系统的 /var 目录(容器外部):

cd /var
# du -sh *
511M	cache
20K	composetest
62G	discourse
1.6G	docker
8.0K	legacy
52G	lib
4.0K	local
0	lock
4.0K	locks
5.7G	log
24K	logs
64K	mail
4.0K	opt
4.0K	registry
4.0K	shared
1.9M	spool
48K	tmp
25G	 linux_app
2.2G	www

我并非想泼冷水,但在四处提出大量针对 Discourse 的“修复方案”之前,最好能 100% 确认 Discourse 备份 cron 任务确实是问题的根源。

我们目前的 Discourse 备份流程从未出现过任何问题,此外,管理主机文件系统本身并不是 Discourse 的任务。

如下所示:

du

Filesystem     1K-blocks      Used Available Use% Mounted on
udev            32892500         0  32892500   0% /dev
tmpfs            6584232      2136   6582096   1% /run
/dev/md2       470927632 215969956 230966124  49% /
tmpfs           32921160         0  32921160   0% /dev/shm
tmpfs               5120         0      5120   0% /run/lock
tmpfs           32921160         0  32921160   0% /sys/fs/cgroup
/dev/md0          482922     75082    382906  17% /boot
/dev/sda1         244988      4636    240353   2% /boot/efi
tmpfs            6584232         0   6584232   0% /run/user/1000
overlay        470927632 215969956 230966124  49% /var/lib/docker/overlay2/0f8be368b0154285423630ad50148ee2d5fdcb357c46125eafa7374ca34ef29a/merged
shm               524288      1620    522668   1% /var/lib/docker/containers/ca7b55fc5a0c123f7b2b1234ea210aa8286a34167cba9344b7929547bd323c9b/mounts/shm
overlay        470927632 215969956 230966124  49% /var/lib/docker/overlay2/7cd7e8b5b35b496eaed68753cc995e9303499a24721062055e2f06beb07e26c8/merged
shm                65536         0     65536   0% /var/lib/docker/containers/3cc0c90c3e3a5db6692e7b5d21727fbb1c13c8e07e48e4f6d954214fc03694a9/mounts/shm
overlay        470927632 215969956 230966124  49% /var/lib/docker/overlay2/31533fdf68033eed96dab4f9df89025ea3dab172ed48b6ce6431840a8df1c8ea/merged
shm               524288         0    524288   0% /var/lib/docker/containers/631fbabedda9a430dd8204ec66fb45c7514d948025124171b960ea424e28d5d4/mounts/shm
overlay        470927632 215969956 230966124  49% /var/lib/docker/overlay2/7a3ba2223ee93bc868b52b3707799d0fd7b4ca6dcc0df29f20c2c98a53903ff1/merged
shm                65536         0     65536   0% /var/lib/docker/containers/7a145366268c8ac5543a4555dc1bfc63c1e85a654e4c793e96fc2cc2e8514388/mounts/shm
overlay        470927632 215969956 230966124  49% /var/lib/docker/overlay2/add4bdd7bd88df7a0e05dff21896d3ef796f7cf2ff9759e0bb04b1953f16cd95/merged
shm                65536         0     65536   0% /var/lib/docker/containers/123743e122089b94660a6bdd2a9e55055ad91b6f75cce4ac760f36066bcf14d0/mounts/shm
overlay        470927632 215969956 230966124  49% /var/lib/docker/overlay2/b376ff32eaac0c58463e8b99b6db9ec0da3405c3f7a9f00b5430f10e07d372b0/merged
shm               524288         0    524288   0% /var/lib/docker/containers/63c52bc571b5f0d2544417da10efc37d3957e7a38f44bc8325145e795ee29559/mounts/shm

让我们看看 Docker 文件:

# cd /var/lib
# du -sh docker
30G	docker

我们的 Docker 镜像会定期修剪和清理。

@bartv 正确地建议从这里开始:

我建议先从找出是哪个目录爆满开始。我的标准做法是进入 /var/discourse,然后运行 du -h -d 1。选择最大的目录,进入其中并重复此过程,直到找到可疑目录。一旦找到,这可能会为您提供一些线索,说明发生了什么。

这是一个不错的开端,但主机文件系统上还有很多其他位置可能导致文件系统填满,包括 Docker、core 文件等。

仅凭一张显示每日出现一次尖峰百分比的图表,还不足以有把握地断定 Discourse 备份 cron 进程是根本原因。它可能是,但也可能不是,基于目前的证据!

6 个赞

太好了,我会试试你提到的所有内容。谢谢。

1 个赞

没错,这显然是一次备份操作。

不,已有充分证据:除了一个例外,使用量峰值均呈两天一次的间隔出现,而备份频率也设置为两天一次。此外,我们在 Meta 上的过往经验也表明,这正是此类故障的典型表现。

没错,这是一个面向未来的可靠方案。不过,对于开始遇到 VPS 磁盘空间限制的用户,我们的首要建议是使用 机器外上传存储,并配合 S3 机制

8 个赞

既然 @pnoeric 正试图将图片移出 S3,那么在仍位于 S3 的备份中存储所有图片的多份副本,就无法实现“移出 S3

4 个赞

我的情况是,我有很多图片,这意味着当用户查看这些图片时,会产生大量的传输带宽。因此,当图片托管在 Amazon S3 上时,带宽费用才是真正让我难以承受的原因。特别是当我意识到可以将所有图片存储在 DigitalOcean(DO)的 Droplet 上,并且这些存储和带宽费用已经包含在我已有的付费套餐中时(未来某个时候,也许将数据移回 S3 会有意义,或者再次升级 DO Droplet 可能更划算……)。

所以我最初使用的是 S3,后来才发现了自己的错误。因此,我现在的情况是,利用你提供的优秀代码,将所有图片从 S3 迁移回 DO。

在 S3 上保留完整备份(包括所有图片)则是另一回事——这些备份存放在 S3 的“冷存储”中,除非出现问题,否则不会被访问,因此不会产生高额的带宽费用。

另外:我一直在思考备份和磁盘使用的问题。我仍然认为这里缺少了一些东西。也许只是一个警告信息,或者更好的文档说明。但我的 Discourse 实例当时只使用了 60% 的磁盘空间,而异地备份却失败了。如果能提供某种磁盘空间需求的估算,或者在磁盘空间不足时发出警告,似乎总比现在的情况要好。而现在的情况是:由于空间不足,连续几天没有备份,随后发生严重崩溃,导致论坛完全离线。:-\

@riking 甚至说过“备份是导致此类故障的常见原因。”那么 Discourse 实例是否经常因为备份失败且没有潜在问题预警而崩溃?)

换一种更简单的说法,从 3 万英尺高空俯瞰:如果一个软件的基本功能(自动备份)会导致整个系统离线,这似乎是一个设计缺陷。尤其是我们讨论的这个功能,仅仅是利用磁盘空间来准备备份,甚至并不将备份存储在同一块磁盘上。

1 个赞

不,他的意思是,通过任何服务器上的任何软件进行备份,都可能填满磁盘并引发问题。

3 个赞

当然,但这就是为什么你要用 CDN 来前置 S3。不要直接从 S3 提供图片,那样会贵得离谱 :scream:。你可以轻松使用 CloudFront 甚至 CloudFlare 来前置 S3。CloudFlare 的免费套餐就能实现这一点。

此外,将它们本地存储也是个很糟糕的主意,你将被迫不必要地升级你的 VPS。本地 SSD 的成本会高得多。

7 个赞

啊,好的,明白了。

那我该如何知道 Discourse 准备备份可能需要多少磁盘空间呢?软件并没有告诉我,也许明天就会变成 500 GB,导致我的 Digital Ocean 服务器再次宕机。:man_shrugging:t2: 至少如果我能做个粗略估算,就能尽量掌控局面。

哇,真是个好主意,我从来没想过。那我是不是应该在我的 Amazon 存储桶前面加一层 CDN,然后告诉 Discourse 使用 S3 来提供所有资源?(就像我之前那样?哈哈)

3 个赞