头像迁移到 S3 兼容的 R2 后加载时间过长

你好,

我刚迁移到 R2,一切都非常顺利。所有图片都使用了 S3 CDN 链接。但我发现了一个问题:头像加载时间很长。平均需要 3 到 4 秒,无论我是点击用户头像还是查看帖子内部。这是否正常?

嗯,我怀疑可能是以下三种问题之一,但对我来说最有可能的是即时调整大小。

1. 即时头像调整大小

当你将上传迁移到 R2 时,它移动了原始图像;然而,Discourse 使用多种不同尺寸的头像(例如帖子中为 45px,用户卡片中为 120px)。

如果这些特定优化尺寸迁移不完全,或者尚未生成,Discourse 必须在用户点击时同步生成它们:

  1. Discourse 从 R2 下载原始头像到本地服务器
  2. 使用 ImageMagick 调整大小
  3. 将新尺寸上传回 R2
  4. 将浏览器重定向到新 URL,此过程需要 3 到 4 秒

验证方法: 硬刷新页面——如果头像第一次加载需要 3-4 秒,但第二次加载立即显示,那么这正是正在发生的事情。

修复方法: 随着用户浏览和尺寸生成,这将自然修复。但你可以通过强制服务器在后台预生成所有头像来立即修复它,方法是 SSH 进入你的服务器并运行:

./launcher enter app
rake avatars:refresh

2. 3 秒 IPv6 超时

如果头像在多次刷新后每次仍然需要 3-4 秒,它们可能遇到了网络超时。

Cloudflare R2 API 端点是双栈的,即它们同时使用 IPv4 和 IPv6。如果你的服务器 Droplet 分配了 IPv6 地址,但主机的 IPv6 网关路由不正确,Ruby 内部连接到 R2 存储桶时将首先尝试 IPv6,挂起 3 秒(这是 Linux TCP 的默认超时),失败,然后立即使用 IPv4 成功。

验证方法: SSH 进入服务器并运行:

curl -I -6 https://cloudflare.com

如果它挂起几秒钟并失败,则服务器的 IPv6 已损坏,导致每个内部 S3 API 检查都遭受 3 秒延迟。

修复方法: 你需要修复主机控制面板中的 IPv6 路由,或者甚至完全禁用 Droplet 上的 IPv6。

3. Gravatar 延迟

如果你的网站配置为检查 Gravatar 更新,它可能在渲染头像之前会 ping Gravatar 的外部服务器。如果服务器的出站连接缓慢(通常也与 DNS 或 IPv6 有关),它可能会阻止头像渲染。

验证方法: 在服务器上运行此命令
curl -I -6 https://gravatar.com
如果它挂起 3 秒,则 IPv6 已损坏(见上文)

与 Gravatar 相关的修复: 在你的 Discourse 设置中,转到 automatically download gravatars(自动下载 Gravatar),暂时关闭它,看看是否能修复——我认为这不是问题,但如果是,你可以保持设置关闭,或者如上所述修复 IPv6 路由,或者更改 DNS 解析器。

感谢您的快速回复。我想我之前已经尝试过 rake avatars:refresh 了,但我不完全确定。

以前对我有效、能让头像立即打开的方法是:第一次点击时它会加载,第二次点击时就能瞬间打开。但这可能是由于缓存导致的。另外,我刚刚测试了您的第二个建议,返回的是“HTTP/2 301”,并附带其他几行信息。第三个建议的情况也相同。由于我需要恢复快照,我将在几天后再次运行 avatars:refresh。再次感谢!

Gravatar

server: nginx
date: Mon, 22 Jun 2026 19:29:00 GMT
content-type: text/html; charset=utf-8
content-length: 0
content-language: en
expires: Wed, 11 Jan 1984 05:00:00 GMT
cache-control: no-cache, must-revalidate, max-age=0
x-redirect-by: Gravatar
location: https://en.gravatar.com/
alt-svc: h3=":443"; ma=86400
strict-transport-security: max-age=31536000; includeSubdomains; preload

CF

HTTP/2 301
date: Mon, 22 Jun 2026 19:27:00 GMT
content-type: text/html
content-length: 167
location: https://www.cloudflare.com/
cache-control: max-age=3600
expires: Mon, 22 Jun 2026 20:26:59 GMT
set-cookie: __cf_bm=eBP2aJ7Eg30nHPuvMMNxxKrgNtcNwKs0WDgnYyONeus-1782156420-1.0.1.1-sXpW27iuhGDF615cOfwNFybH4IMxgvZy3uA_3X_o..402T_3KSgT7CSymipL5RjdpGe3raWEqsVxQFFLPKRoDjfoT7B.0rqyDt.osbkOF98; path=/; expires=Mon, 22-Jun-26 19:57:00 GMT; domain=.cloudflare.com; HttpOnly; Secure; SameSite=None
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=QfYqSekEDPJHC2k%2BMjHN0cGjz172tmUWe2GSR8EgwNLh3TGjFYkQ0vwPxlzY1NcBcKFOMaAi4FlgjqjhETOOtHf%2BH9KdQSvqN3OME2Uh1i4nHIw%2Fy1qkvSpf4jxDchM7CaDW80tJkjBV4OqF"}],"group":"cf-nel","max_age":604800}
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
strict-transport-security: max-age=15780000; includeSubDomains
server: cloudflare
cf-ray: a0fda5d8ecd6b26d-LAX
alt-svc: h3=":443"; ma=86400

是的,根据你的回复,我几乎可以确定是问题 #1,因为针对 Cloudflare 和 Gravatar 的 curl 命令结果看起来都符合预期。方便的时候请尝试运行 rake avatars:refresh,并告诉我是否有效。