分块备份上传器超出 Discourse 请求速率限制

我们的一位客户在通过管理界面上传本地 Discourse 备份时遇到了一个可复现的问题。

备份上传器使用固定的 5 MB 分块,在足够快的连接下,可能会生成足够多的请求,从而超过 Discourse 自身的应用层请求速率限制。当这种情况发生时,服务器会返回 HTTP 429,但分块上传器不会重试 429 响应,也不会遵守 Retry-After 请求头。结果,整个备份上传都会失败。

非 2xx 响应会被转换为 错误

if (ev.target.status < 200 || ev.target.status >= 300) {
  const error = new Error("Non 2xx");
  error.source = ev.target;
  reject(error);
  return;
}

重试 逻辑如下:

_shouldRetry(err) {
  if (err.source && typeof err.source.status === "number") {
    const { status } = err.source;

    return (
      status === 0 ||
      status === 409 ||
      status === 423 ||
      (status >= 500 && status < 600)
    );
  }

  return false;
}

因此,HTTP 429 明确被标记为不可重试。

只要出现一次 429 响应,分块上传的 Promise 就会失败,最终导致整个备份上传触发 upload-error

此外,也没有对 Retry-After 响应头进行处理。


我找到了一个 2021 年的主题,虽然很快跑题了,但看起来正是同样的问题