Fetch 本身不支持自动主备切换,需在应用层手动实现:维护备用地址列表,按序重试并结合 AbortController 超时控制、状态码判断(如5xx/503)及可选内存级健康标记,避免依赖不可靠的HTTP重定向。

Fetch 本身不支持自动主备切换或重定向到其他服务器节点,它只是发起单次 HTTP 请求。要实现“主备服务器自动切换”,需要在应用层手动处理失败重试 + 备用地址列表 + 健康状态感知(可选),而不是依赖浏览器原生重定向(如 302)——因为服务端无法预知客户端当前连接的是主还是备,且跨域、鉴权、请求体重放等问题会让服务端重定向不可靠。
1. 手动维护节点列表并顺序重试
最常用也最可控的方式:预先配置一组 API 地址(如 ['https://api-main.example.com', 'https://api-backup.example.com']),按顺序发起 fetch,遇到网络错误、超时或明确的 5xx/4xx(如 503)时,自动尝试下一个节点。
- 使用
AbortController控制单次请求超时,避免卡死 - 对非 2xx 响应(尤其是 502/503/504)视为节点不可用,触发降级
- 避免无限重试,建议最多 2–3 次(含主节点)
2. 封装一个带故障转移的 fetch 函数
例如:
async function fetchWithFailover(url, options = {}, endpoints = [
'https://api-main.example.com',
'https://api-backup.example.com'
]) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 8000);
<p>for (let i = 0; i < endpoints.length; i++) {
try {
const fullUrl = new URL(url, endpoints[i]).href;
const res = await fetch(fullUrl, {
...options,
signal: controller.signal
});</p><pre class="brush:php;toolbar:false;"> clearTimeout(timeoutId);
if (res.ok) return res;
// 主动拒绝 5xx 和特定 4xx(如 503 表示服务不可用)
if (res.status >= 500 || res.status === 503) {
continue; // 尝试下一个节点
}
return res; // 其他 4xx(如 401/404)直接返回,不降级
} catch (err) {
if (i === endpoints.length - 1) throw err; // 最后一个节点也失败,抛出
// 忽略本次错误,继续下一轮
}} }
3. 可选:加入简易健康标记(内存级)
避免频繁试探已知故障节点,可在内存中记录最近失败的 endpoint 和时间,短时间(如 60 秒)内跳过它。注意:该状态不跨页面刷新,适合单页应用临时规避。
立即学习“Java免费学习笔记(深入)”;
- 用
Map存储endpoint → timestamp - 重试前检查是否在“熔断期”,跳过失效节点
- 成功响应后清除对应标记
4. 不推荐依赖 HTTP 重定向做主备切换
虽然服务端可返回 302 重定向到备用地址,但存在明显问题:
- POST/PUT 等非幂等请求,浏览器对 302 会改为 GET,导致数据丢失或语义错误
- 跨域重定向需服务端精确配置 CORS,且 credentials 传递受限
- 客户端无法区分是“临时重定向”还是“永久迁移”,难以做节点状态管理
- 无法控制重试次数、超时、错误分类等关键逻辑


















