重烘焙旧帖子在重命名 S3 存储桶后不会拉取新的 S3 CDN URL

安装 Discourse(2.7.0.beta1)并导入旧的 Google Groups 帖子后,我添加了 S3 存储桶/密钥配置(但未配置 CDN URL),然后运行了以下命令:

rake uploads:migrate_to_s3

该命令似乎运行顺利。所有图片都已上传到 S3,Discourse 正尝试通过自动生成的 S3 URL 访问它们,类似于:

https://ortus-discourse.s3.dualstack.us-west-2.amazonaws.com/original/1X/75747ca17a3ca01f298f836691e1990916bafccb.png

随后,我重命名了存储桶(改为 ortus-discourse-uploads),并在其前端配置了 CloudFront 分发,同时设置了一个由 Cloudflare 配置的 CNAME:

https://communitycdn.ortussolutions.com/

CNAME、CloudFront 和 S3 目前均运行正常。像这样的 URL 可以正确提供存储桶中的图片:

https://communitycdn.ortussolutions.com/original/1X/75747ca17a3ca01f298f836691e1990916bafccb.png

然而,问题在于 Discourse 完全停留在旧的 ortus-discourse.s3.dualstack.us-west-2.amazonaws.com 域名上(由于存储桶已重命名,该域名已失效)。无论我重建容器多少次,或重新烘焙旧帖子多少次,我都无法让 Discourse 使用新的 CDN URL。我在谷歌上搜索了一整天,并重新烘焙了大约十几次(在 app 容器内),尝试了各种设置。每个论坛帖子给出的建议都是“重建并重新烘焙”,但这并没有生效。

出问题的不仅仅是帖子中的图片,甚至连 <link rel="icon" type="image/png" href=""> 和网站标志都停留在旧域名上,无法使用 S3 CDN URL。

以下是我当前的 S3 设置:

  DISCOURSE_S3_ACCESS_KEY_ID: '********'
  DISCOURSE_S3_SECRET_ACCESS_KEY: '******'
  DISCOURSE_BACKUP_LOCATION: 's3'
  DISCOURSE_ENABLE_S3_UPLOADS: true
  DISCOURSE_S3_BUCKET: 'ortus-discourse-uploads'
  DISCOURSE_S3_UPLOAD_BUCKET: 'ortus-discourse-uploads'
  DISCOURSE_S3_BACKUP_BUCKET: 'ortus-discourse-backups'
  DISCOURSE_S3_REGION: 'us-west-2'
  DISCOURSE_S3_CDN_URL: https://communitycdn.ortussolutions.com

  DISCOURSE_CDN_URL: https://community.ortussolutions.com

我甚至尝试在帖子中将旧 URL 映射到新 URL,如下所示:

rake posts:remap["ortus-discourse.s3.dualstack.us-west-2.amazonaws.com","communitycdn.ortussolutions.com"]

但该命令提示“0 posts affected”(未影响任何帖子)。

在我的环境变量或数据库设置中,没有任何地方引用旧的存储桶名称 ortus-discourse,因此我无法弄清楚 Discourse 是从哪里获取该名称的。我是 Discourse 的新手,也不是 Ruby 开发者,所以我只查看了 app.yml、管理 UI 以及我在论坛上找到的 rake 命令的输出结果,没有深入探究。

Uploads 表中这些上传记录的价值是多少?

./launcher enter app
rails c
Upload.all.sample(10).pluck(:url)

@Falco 谢谢你的回复。这是该命令的输出结果。

root@discourse-app:/var/www/discourse# rails c
Upload.all.sample(10).pluck(:url)
[1] pry(main)> Upload.all.sample(10).pluck(:url)
=> ["//ortus-discourse.s3.dualstack.us-west-2.amazonaws.com/original/1X/52b3aff4e63a7e38bef42d469bafd1ed7c1cc1a2.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/9f90374a280a4681332bcd2191b8de43462f8776.png",
 "//ortus-discourse.s3.dualstack.us-west-2.amazonaws.com/original/1X/29691fba566fc998a966aa93859753e3cf0b8528.cfc",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/6ae912ced40d60adc1356c1d7acf144b0fa0985a.jpeg",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/4dfe5b48fc8cb5d79880d70355c34d7ed02be812.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/897c4b4e755c1c8e93224a27187dc631a02e4388.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/59886f322e6834b567d473138108fab6e0f33764.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/e3e3429d63155cf0d850e161846d187bc6f273ea.jpeg",
 "//ortus-discourse.s3.dualstack.us-west-2.amazonaws.com/original/1X/1b701869b4b235daa8d6a9a7728766f3b4e69814.txt",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/c83aaee941462d47ef91f0c6448257d07487b231.png"]
[2] pry(main)>

确实有不少文件仍指向旧的存储桶。

您需要执行的重新映射命令如下:

./launcher enter app
rails c
DbHelper.remap("ortus-discourse.s3.dualstack.us-west-2.amazonaws.com", "ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com")

请在执行前进行备份,因为此操作无法撤销。

@Falco 再次感谢。我执行了两次重映射:

DbHelper.remap("ortus-discourse.s3.dualstack.us-west-2.amazonaws.com", "communitycdn.ortussolutions.com")
DbHelper.remap("ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com", "communitycdn.ortussolutions.com")

我重新构建了镜像,这解决了网站页头徽标等问题。我现在正在重新处理所有帖子,看看是否能修复帖子中的图片,但这需要一些时间。


在等待重新处理的过程中,这里到底出了什么问题?这是 Discourse 的一个 bug 吗?导致我的上传内容卡在旧 URL 上,无法切换到新 URL?

我阅读了像这样的一篇帖子,它讨论了更改 CDN URL,但其中只提到了替换帖子中的字符串(这并没有起作用),完全没有提及 DbHelper 重映射。How do I change the legacy CDN URLs of images in posts?

我甚至尝试重新运行导入到 S3 的 rake 脚本,但收到了一个错误(抱歉,我当时没有记下具体错误信息)。

我还发现了一个 migrate_from_s3 rake 脚本,差点就运行它看看能否从头开始,但后来我发现了 这里的一篇论坛帖子,其中指出如果我运行它,会破坏我的数据库,所以我没有碰它。

我现在不知道当初应该怎么做才对,或者哪篇论坛帖子能解答我的问题。(在发帖之前,我确实非常努力地尝试自己解决这个问题!)

遗憾的是,重新生成似乎并未修复嵌入帖子中的图片。有趣的是,如果我选择一篇旧帖子并编辑它,会看到图片以类似以下的方式呈现:

![COMMANDBOXERROR.png|1169x984](upload://yTDVQSa4wbIeLGEZvE7muXe8sAJ.png)

但在查看帖子时,帖子中只有一大片空白区域,指向:

https://community.ortussolutions.com/images/transparent.png

这是最近发生的变化。昨天大部分时间里,这些图片只是指向旧的错误 S3 URL,但在昨晚或今天的某个时候,透明 PNG 出现了。

嗯,这可不是我在回复中让你做的::face_with_raised_eyebrow:

在 uploads 表中,我们期望的是 S3 位置,它仅在 Markdown 的 cook 过程中被替换为 CDN。

你把 CDN 放到了 Uploads 表中,但这并不是软件通常的做法。

对此我很抱歉,我原以为你只是没有仔细阅读主题帖(OP),没注意到我提到了 Cloudflare 分发设置,以及我需要调整它以使用我的实际 URL。我没想到那个不需要的 URL 实际上存储在数据库的任何地方。我差点就回复问你是否是这个意思,但当时我觉得我接下来该做什么是很明显的。

没关系,我可以轻松地将它们重新映射回 S3 URL。这是一个新安装的 Discourse,所有上传的内容都存储在同一个位置,所以切换起来很容易。

我关于上一帖中出错原因的疑问仍然有效。

我认为问题很简单,我们不支持更改对象存储(Object Storage)的存储桶。

这里的“支持”意味着你无法更改存储桶并期望其正常工作,也没有相关的书面指南或预打包的 rake 任务。因此,如果你最终需要更改存储桶,则必须进行一些数据库调整。

好的,这很合理。那么,我犯下的那个大错误是:重命名了 S3 存储桶,并误以为在管理后台更新存储桶名称就能解决所有问题。或许在管理后台编辑存储桶名称时添加一个警告会有所帮助。(我最初是在管理后台设置这些参数,后来才切换到使用环境变量,当时以为那样会有所帮助)显然,上传后更改存储桶名称会导致问题这一点并不明确。

我已将域名重新映射回正确的 AWS S3 域名:

DbHelper.remap("communitycdn.ortussolutions.com", "ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com")
[1] pry(main)> Upload.all.sample(10).pluck(:url)
=> ["//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/fc05f9be9b783479819fec68b1d8e493110007a4.cfc",
 "/images/d-logo-sketch-small.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/50f0d6f260cdb4ef91e29023d92b46df096ab34e.cfc",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/65d80cddc6dc15b9a4d1b9e9d88cc9a8928c5316.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/a86aa2a12183428f3289caa95787ea16f22e2e4d.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/9f76b5238b147a60c8ad5f65bd7fa4bb6b58d852.png",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/6a4c9b992e6cd8a15ddeaec0d158ebd473164525.zip",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/3a532dec6390d5087ed6154fc0335c2c0f1ea543.zip",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/93420848249ecea2261d405e46f7f450cc02a3af.txt",
 "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/d67c39e06ce624b9deb7625dd041d21cffd96df9.png"]

我已重新构建应用程序,现在正在重新烘焙帖子。希望第 37 次尝试能带来好运 :slight_smile:

所有上传均已配置正确的 S3 存储桶 URL,容器已重新构建,且 30,000 篇帖子已重新生成。但我仍然看到所有图片位置显示为:

/images/transparent.png

编辑帖子时仍显示如下内容:

![COMMANDBOXERROR.png|1169x984](upload://yTDVQSa4wbIeLGEZvE7muXe8sAJ.png)

值得注意的是,其他附件(如 zip 文件)现在可以正常工作。

是否缺少某些必要步骤,才能使旧帖子中的嵌入图片正常显示?

能否打印与 yTDVQSa4wbIeLGEZvE7muXe8sAJ 对应的 Upload 对象的属性?

我很乐意帮忙,但这个问题我需要一些协助。我是一名开发者,但不是 Ruby 开发者。我已经弄明白如何打印出随机上传的所有属性,方法如下:

[17] pry(main)> Upload.all.sample(1)
=> [#<Upload:0x00005633230f8af0
  id: 353,
  user_id: 273,
  original_filename: "helloWorldF.zip",
  filesize: 50542,
  width: nil,
  height: nil,
  url: "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/3a532dec6390d5087ed6154fc0335c2c0f1ea543.zip",
  created_at: Wed, 30 Dec 2020 18:46:31 UTC +00:00,
  updated_at: Wed, 30 Dec 2020 18:46:31 UTC +00:00,
  sha1: "3a532dec6390d5087ed6154fc0335c2c0f1ea543",
  origin: nil,
  retain_hours: nil,
  extension: "zip",
  thumbnail_width: nil,
  thumbnail_height: nil,
  etag: nil,
  secure: false,
  access_control_post_id: nil,
  original_sha1: nil,
  animated: nil,
  verification_status: 1>]

我还找到了一些关于 ROR 中 Active Record 的参考资料,用于查找特定记录,但我在其中找不到任何与 yTDVQSa4wbIeLGEZvE7muXe8sAJ 相似的数据。我该如何找到对应的上传记录?

哦,好消息。在研究如何查找上传记录时,我发现了这篇帖子,它展示了如何将 base62 字符串转换为 sha1 哈希。

帖子中提到,那些只显示 transparent.png 的图片已被“tombstoned”(标记为废弃)。我不太确定这具体意味着什么,但我推测是某个进程在夜间运行,当时这些图片已损坏,于是将它们标记为未使用。我成功运行了以下命令:

rake uploads:recover_from_tombstone

看起来我所有嵌入的图片都已恢复,现在都指向我的 S3 CDN 了!

顺便提一下,以下是我如何从 yTDVQSa4wbIeLGEZvE7muXe8sAJ 这个字符串开始找到对应的 Upload 记录的:

[14] pry(main)> Base62.decode("yTDVQSa4wbIeLGEZvE7muXe8sAJ").to_s(16)
=> "f49428d6af35d7e0414408ccb65e7316f5003215"
[15] pry(main)> Upload.where( "original_filename ilike '%f49428d6af35d7e0414408ccb65e7316f5003215%'" )
=> [#<Upload:0x000056313aa91fe8
  id: 899,
  user_id: 549,
  original_filename: "f49428d6af35d7e0414408ccb65e7316f5003215.png",
  filesize: 25514,
  width: 1169,
  height: 984,
  url: "//ortus-discourse-uploads.s3.dualstack.us-west-2.amazonaws.com/original/1X/f49428d6af35d7e0414408ccb65e7316f5003215.png",
  created_at: Tue, 12 Jan 2021 23:01:35 UTC +00:00,
  updated_at: Tue, 12 Jan 2021 23:01:36 UTC +00:00,
  sha1: "f49428d6af35d7e0414408ccb65e7316f5003215",
  origin: nil,
  retain_hours: nil,
  extension: "png",
  thumbnail_width: 594,
  thumbnail_height: 500,
  etag: "6977f35ddbf39a4399dc76f92a5079d4",
  secure: false,
  access_control_post_id: nil,
  original_sha1: nil,
  animated: nil,
  verification_status: 1>]

再次感谢你的帮助,@Falco!我是 Discourse 的新手,但你表现得非常耐心且乐于助人 :+1: