恢复后头像丢失。如何找回?

早上好 @ariznaf

在得出该结论之前,能否请您前往所有安装实例,进入每个实例的共享文件夹,并对每个实例执行以下命令,然后将结果反馈回来?

# du -sh uploads

例如,在我们的安装实例中,我执行了以下操作:

原始安装:

# du -sh uploads
2.5G uploads

仅 Socket 安装(修复问题之前):

# du -sh uploads
444K uploads

这为我提供了关键线索,让我意识到需要手动复制 uploads 文件夹;而在明确问题后,解决方案就很简单了。

如果您在所有共享目录中使用 du -sh uploads 检查所有不同的 uploads 文件夹,这将为您提供关于问题根源的重要线索。

如果它们的大小不同,那么您就知道某些上传文件缺失,可以手动进行修正。

如果它们都相同(这种情况不太可能),那么问题就会变得更有意思了 :slight_smile:

我已经找到了问题(但还没找到解决方案)。
问题不在于恢复过程本身,而在于更改服务器名称。

让我解释一下我是如何进行恢复的(以防有遗漏的步骤)。

我从 GitHub 下载了 Discourse 的 fresh copy。
我运行了 docker-setup 过程。
在运行应用并继续恢复之前,我编辑了 app.yml 以配置 socket 访问权限。
并将主机名更改为 b.domain.com(原始为 a.domain.com)。

使用 SSL 配置了 nginx 反向代理,将 443 端口的 https 流量定向到 Discourse socket。
然后重新构建(launcher rebuild app)并重启 nginx(service nginx restart)。
我访问了 https://b.domain.com 进行 Discourse 的首次配置。
将其配置为从 S3 恢复,并恢复了最新的数据库和上传备份(不含缩略图)。
恢复后,您会被自动登出。
我编辑了 app.yml,从旧站点复制 app.yml(以获得相同的配置和插件)。
在 app.yml 中将主机名更改为 b.domain.com

再次重新构建并重启 nginx。

问题依然存在:所有更改过个人资料的用户头像(缩略图)都被替换成了默认的白色头像。
左上角的 Logo 也丢失了。

@Stephen force_https 已启用(与原始服务器相同,当时没有问题)。我尝试过启用和禁用它,但没有任何效果。我将其保持为启用状态,因为我们需要通过 https 访问网站(无论如何,我们的 nginx 配置中 http:80 流量已永久重定向到 https:443)。

@riking 我使用了 sidekiq 并触发了 avatarmissing 任务,该任务似乎在几毫秒内就完成了。为了以防这是一个耗时的过程,我等待了近 24 小时,看看个人资料图片是否被重建。
但今天问题依旧:没有头像图片(针对上传了个人资料图片的用户),也没有 Logo 图片。

之后,我尝试查看问题是否出在名称更改上,正如 @Stephen 所建议的那样。

我将 app.yml 和 nginx 中的主机名改回 a.domain.com(原始名称),并重新构建和重启了 nginx。
我修改了本地的 hosts 文件,将 a.domain.com 指向新服务器的 IP,并尝试 ping 以确认它正在访问新的 IP。

然后奇迹出现了:头像和我们的个人资料都回来了。

所以问题不在于恢复过程本身,问题在于 URL 的完整路径被保存了,并且系统试图从错误的位置访问它们。
这很奇怪,因为原始服务器仍然在运行(即使从错误的位置访问,它也应该能找到图片,即原始服务器而不是新服务器)。

但无论如何,问题不在于恢复过程,也不在于由于某种损坏而需要重新上传图片。

问题在于服务器名称的更改。

现在的问题是:如何将 Discourse 论坛从一个域名/主机名迁移到另一个?

我再次尝试将主机名更改为 b.domain.com,但毫无进展。

看起来使用旧名称时一切正常(但我现在怀疑它正在从仍在线的旧服务器获取图片和其他内容,因为即使我已在 hosts 文件中将 a.domain.com 的 IP 地址更改为新地址,我仍然收到来自旧服务器新帖子的新帖子和通知)。

我按照这篇帖子中的说明更改了主机名:

我曾以为将 discourse 重新映射 a.domain.comb.domain.com 会解决问题。
即使我运行了 rake posts:rebake,结果依然相同。

头像、标志以及帖子中插入的图片都已丢失。

最后,正如 @neounix 所建议的,我重新解压了所有上传文件以替换 shared/standalone/uploads/ 中的目标路径,但依然无效,结果没有变化。

您的数据库中真的有什么有价值的信息吗?与其担心服务器迁移,不如直接从头开始可能更简单。

几个月前论坛建立以来的所有数据和帖子怎么办?

正如我之前所说,我通过停止服务器、将所有数据复制到新服务器并重新启动的方式,成功地将服务器迁移到了另一台服务器上。

但支持团队告诉我,正确的做法是使用标准备份并恢复数据库。

我尝试这样做,但每次都遇到某种问题。
我还需要一台测试服务器,以便在应用到生产环境之前测试插件、更改或升级的效果。

我不能等到服务器崩溃了,才去测试能否成功恢复。

到目前为止,所有的恢复测试都以某种问题告终,导致系统无法正常运行,图片或其他内容丢失。

关于这一系列事件的后续:

https://meta.discourse.org/t/postgresql-12-update/151236/193

我尝试了“在不同 Discourse 实例上进行备份和还原”的方法,现在却遇到了这个问题。我试遍了所有已知的方法(如 Sidekiq 任务、Rebake 等)……是否有任何线索可能说明导致此问题的原因?仅供我尝试找出一些线索。

(有一件事我必须承认,经过这一切,我已经从“嗯,我大概懂一点”进阶到了 PostgreSQL 博士、Redis 博士…… :stuck_out_tongue: 只需要再掌握 Ruby 和本地开发环境,我就能为社区做些贡献了 :P)

所有头像都消失了吗,还是只有一部分?自定义头像本质上是“上传”,其他上传是否按预期工作?

进入 Rails 控制台,检查数据库中非功能头像的记录……它们的 URL、文件大小、宽度、高度、扩展名 是否正确?

User.find_by_username('Overgrow').user_avatar
User.find_by_username('Overgrow').uploaded_avatar

它们还需要包含优化后的版本。你可以通过以下方式检查:

OptimizedImage.where(upload_id: upload_id).where(version: 2)

首先,非常感谢您的帮助 @Overgrow

所有的头像、表情符号(甚至网站图片,如页眉等)都“存在”,但不可见。对于非头像内容,它们显示为损坏状态;对于头像,则显示为灰色占位符。有些人能够重新上传新的头像,这些新的头像可以正常显示。

我最初尝试运行命令时得到以下结果:

FATAL: 数据库系统处于恢复模式

所以……情况就是这样 :eyes:(我经常遇到“断开连接”的问题,所以我怀疑 这与数据库有关?

但在坚持尝试后,最终得到了以下结果:

User.find_by_username(‘Overgrow’).user_avatar

=> #<UserAvatar:0x000055702722d200
 id: 4,
 user_id: 3,
 custom_upload_id: 20504,
 gravatar_upload_id: 12240,
 last_gravatar_download_attempt: Thu, 21 May 2020 10:16:55 UTC +00:00,
 created_at: Sat, 30 May 2019 16:33:16 UTC +00:00,
 updated_at: Thu, 21 May 2020 10:16:55 UTC +00:00>

(今天尝试重新上传一个新的头像,但不起作用)。

User.find_by_username(‘Overgrow’).uploaded_avatar

=> #<Upload:0x00005555cd911b58
 id: 20504,
 user_id: 3,
 original_filename: "16_2.png.jpg",
 filesize: 56220,
 width: 360,
 height: 360,
 url: "/uploads/default/original/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8.jpeg",
 created_at: Thu, 15 Aug 2019 20:02:47 UTC +00:00,
 updated_at: Thu, 15 Aug 2019 20:02:47 UTC +00:00,
 sha1: "63347a46c0ca945f53613722a73c233484d642c8",
 origin: nil,
 retain_hours: nil,
 extension: "jpeg",
 thumbnail_width: 360,
 thumbnail_height: 360,
 etag: nil,
 secure: false,
 access_control_post_id: nil,
 original_sha1: nil>

OptimizedImage.where(upload_id: 20504).where(version: 2)

=> [#<OptimizedImage:0x000056366a01c1a0
  id: 95962,
  sha1: "5a32b5cc3e6f5c58d88a3c92a23076980a8ce840",
  extension: ".jpeg",
  width: 200,
  height: 200,
  upload_id: 20504,
  url: "/uploads/default/optimized/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8_2_200x200.jpeg",
  filesize: 28916,
  etag: nil,
  version: 2>,
 #<OptimizedImage:0x000056366a0741e8
  id: 95942,
  sha1: "ee353c9e23511b471e1a59c1f71a2ded3e366b1e",
  extension: ".jpeg",
  width: 20,
  height: 20,
  upload_id: 20504,
  url: "/uploads/default/optimized/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8_2_20x20.jpeg",
  filesize: 1270,
  etag: nil,
  version: 2>,
 #<OptimizedImage:0x000056366a074120
  id: 95943,
  sha1: "944fa9fc542a79a5c50394c75022bf84ace297e5",
  extension: ".jpeg",
  width: 30,
  height: 30,
  upload_id: 20504,
  url: "/uploads/default/optimized/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8_2_30x30.jpeg",
  filesize: 1952,
  etag: nil,
  version: 2>,
 #<OptimizedImage:0x000056366a074058
  id: 95944,
  sha1: "983490e58bed58c971ffa44e440b02ce3ea72bba",
  extension: ".jpeg",
  width: 40,
  height: 40,
  upload_id: 20504,
  url: "/uploads/default/optimized/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8_2_40x40.jpeg",
  filesize: 2695,
  etag: nil,
  version: 2>,
 #<OptimizedImage:0x000056366a07bf60

所以,从表面上看,图片确实存在,但无法显示。只能看到默认的灰色头像占位符。

数据库记录层面一切正常。调查时,您可以向上层推进。

当您手动访问您列出的上传链接时,会得到什么结果?

如果我把 /uploads/default/optimized/3X/6/3/63347a46c0ca945f53613722a73c233484d642c8_2_200x200.jpeg(即)放在我的 Discourse 网址后面?我得到的是 404 错误,找不到。

所以……它们不存在吗?(我带着希望问 :P)

请检查来自 /uploads/default/original 的文件 URL,而不仅仅是 /uploads/default/optimized 的。

404 … 这意味着你需要在文件系统中检查 /var/discourse/shared/standalone 内的 uploads 文件夹,并查找实际旧文件的位置(如果存在)。找到它们后,尝试将其位置与新上传的文件(即那些能正常工作的文件)进行比较。

你也可以从备份中手动恢复这些文件。

感谢解释。

我刚进去双重确认了一下,列出的部分路径确实不存在。

奇怪的是,有人尝试上传新文件,但这些新文件也无法正常工作。当你使用我提供的命令查看时,会发现一个同样不存在的路径。Discourse 是如何“映射”这些路径的?因为文件缺失(尽管备份本应将其携带过来)这一点我还能理解,但新上传的文件却指向了“幽灵路径”,这我就完全想不通了。

请检查 uploads 文件夹内的 tombstone 文件夹——是否有部分缺失的文件在那里?

我在 uploads 文件夹里只看到了 default 文件夹……tombstone 文件夹是用于存放已弃用的文件还是类似的东西?

另外,补充一点信息:原来,如果用户尝试上传他们之前已经上传过的同一张图片(即使他们更改了文件名,根据我看到的查询结果,这应该是基于哈希值判断的),图片将无法加载,会显示为空。一旦保存,你就会看到灰色的占位符。

显然,如果你以某种方式修改了图片(即使只是在 Photoshop 中将其另存为不同的格式),就可以重新上传它。

这是正常行为。数据文件的哈希值会存储在数据库中,以避免重复图片。

如果你通过撰写编辑器上传图片,会发生什么?上传会完成吗?预览窗格中会显示图片吗?

如果我编写一条消息并附上图片,它会在预览面板中显示并完成上传,是的,这是正常行为。

那么,这张图片具体是在哪个环节停止显示的?

请检查你看到的该图片的 URL,并追踪到文件系统。

检查无法工作的图片的 URL(通过浏览器中的网页开发工具)。它们之间有什么不同?

也许它们指向的是不同的域名。

第一条消息中我指的是头像(通过用户个人资料),第二条消息指的是编辑器。

因此,在普通消息中,如果您拖放或点击“上传图片”按钮,它将像往常一样无缝工作。

简而言之:

  • 头像不显示,仅显示占位符。
  • 自定义表情符号也不显示。
  • 站点图片(如徽标等)也未显示。
  • 如果在编辑器中上传图片,则可以正常工作。
  • 如果您尝试上传事故前使用的相同头像,则无法生效。其行为是:会执行上传,但在选择默认字母、Gravatar 或上传的框中会显示为空白方块。当您确认选择并页面重新加载后,您将看到灰色占位符。

另外:

  • 没有 Tombstone 文件夹。
  • 旧图片位于(通过您提供的查询所示)不存在的目录中。

让我检查一下域名问题。顺便一提,我在查阅相关信息时尝试了以下操作:

  • 从 Sidekiq 触发 CreateMissingAvatars 任务 → 无成功。
  • 重新生成所有帖子(这有点牵强) → 无成功。
  • 根据 此讨论,由于我在主站点离线时使用不同的域名(实际上是子域名)测试了从备份恢复,因此我怀疑某些 URL 可能不正确,于是运行了以下命令:discourse remap talk.foo.com talk.bar.com → 无成功。

@Iceman

这主要是供你参考,也许信息量有点大,但或许能帮助你从某些细微之处获得一些额外见解,了解我们同时运行三个容器(两个 Web 应用容器和一个数据容器)时遇到的一些有趣现象(以及这如何影响用户头像)。

在我看来,Redis / Sidekiq 作业调度器在并行运行时的工作方式非常有趣(而且非常酷),尤其是在只有一个实例“在用户 Web 端处于活动状态”的情况下:

希望这段结合真实案例的简短讨论能引起你的兴趣。它或许能为你提供一些关于 Discourse 作业调度器、图像优化以及基于我们配置的用户头像的微小见解:

我非常赞赏 Discourse 如何利用 Redis / Sidekiq 来调度后台作业;我认为这是 Discourse 软件架构的关键优势和亮点之一。

注意:这些概念以各种微妙的方式同样适用于备份和恢复过程的不同阶段以及其他(与时间相关的)进程,因此了解 Sidekiq 为何以及如何在后台调度作业是一个很好的做法。

感谢提供信息 @neounix,这对从“我正在学习 Rails 以便提供帮助,但天哪,在尝试修复自己的安装时,学习曲线确实很陡峭”的角度来更好地理解 Discourse 的内部机制非常有帮助::winking_face_with_tongue:

我现在正专注于 Redis/Sidekiq,试图理解为什么某些嵌入内容无法正常工作。我💡认为这可能与“Bake”有关,但由于我还在调试阶段(希望如此),暂时还不能下定论。

关于我目前遇到的问题,多亏了 @Overgrow,我确定了以下几点:

  • 实际上,备份过程确实将文件复制到了备份中,但并未将其恢复到 Discourse 安装中。根据我其他三个问题的状态和/或修复情况,我可能需要在另一个安装中恢复另一个备份并再次测试备份过程,但这可能是所有人都会遇到的问题,目前还不确定。

  • 正因如此,才出现了那些奇怪的行为。

  • 最终我打开了备份文件,并将缺失的文件注入到安装中。这样无需重新 Bake 就恢复了所有内容。

不过,其他问题仍然存在:无法重建数据容器(对此我毫无头绪),以及两个问题让我将注意力集中在 Sidekiq 和事件上,因为它们可能通过这种方式解决:某些 Oneboxes(特别是 YouTube)无法正常工作,以及一些关于“虚假”编辑的通知递归地发送给某些用户,尽管实际上并未发生任何编辑。因此,我认为新安装可能在事件处理方面存在问题,我正在努力找出原因。:man_shrugging: