promise.any 实现多源镜像高可用:并发请求3个差异源,各配独立 abortcontroller 与3–4秒超时,非2xx主动抛错;首个成功 response 返回后按类型注入资源;全失败时用 aggregateerror 降级并监控;需配合qps限流与请求标识防压垮节点。

用 Promise.any 构建高可用镜像服务器请求方案,核心是“多源并行、择优返回、失败兜底”。它不追求全部成功,只确保最快那个能用——这正是镜像服务最需要的韧性逻辑。
选多个稳定镜像源,并发发起请求
不要只依赖单一 CDN 或镜像地址。至少配置 3 个地理或网络路径差异明显的镜像源(如国内 CDN-A、海外 CDN-B、自建备用节点 C),把它们封装成独立的 fetch Promise:
- 每个镜像 URL 单独配一个
AbortController,避免超时互相干扰 - 统一设超时时间 3–4 秒:短于 2.5s 易误判正常波动,长于 5s 拖慢首屏体验
- fetch 中必须传入
signal,否则 abort 不生效 - 对非 2xx 响应(如 404、503、429)主动 throw,让 Promise.any 自动忽略该路
用 Promise.any 拦截首个成功响应
Promise.any 不会因第一个失败就中断,它会持续等待直到出现首个 fulfilled 的 Promise:
- 返回的是
Response对象,不是原始数据,需手动调用.text()、.json()或.arrayBuffer() - 若所有镜像都失败,会抛出
AggregateError,其errors数组包含每条链路的具体错误(如网络断开、状态码异常、超时等) - 可据此记录日志、上报监控,甚至触发自动降级(比如切到本地缓存或离线 fallback)
加载后动态注入资源,避免阻塞渲染
拿到 Response 后,根据资源类型做轻量级处理,不走 eval、不重刷 DOM:
-
JS 脚本:用
response.text()获取字符串,创建<script></script>标签并插入document.head;注意设置type="text/javascript"和async -
CSS 样式:同样用
response.text(),生成<style></style>标签并 append 到 head;建议加data-mirror-used属性标记来源,便于调试 -
JSON 数据:直接
response.json()解析,交由业务层消费;可加一层 schema 校验,防止镜像被篡改返回非法结构
配合连接池与限流,防止压垮镜像节点
高并发下大量 Promise.any 并行请求可能瞬间打满某镜像源。需前置控制流量:
- 前端可对同一镜像域名做简单 QPS 限制(例如 5s 内最多发起 10 次请求),用 Map + 时间戳实现
- 后端镜像服务应启用连接池(如 Node.js 的
guzzlehttp/promises池化配置),设合理max_connections和wait_timeout - 在请求头中带上
X-Request-From: mirror-client和唯一 traceId,方便镜像方识别和限流










