首页
/ Axios HTTP/2 实战指南:httpVersion 配置、http2Options 调优与 Node.js 会话池实现原理

Axios HTTP/2 实战指南:httpVersion 配置、http2Options 调优与 Node.js 会话池实现原理

2026-09-04 14:49:27作者:董灵辛Dennis

Axios 自 v1.13.0 起在 Node.js 环境的 http 适配器中引入了实验性的 HTTP/2 支持。本文基于官方文档 HTTP/2 页面英文原版),完整讲解 httpVersionhttp2Options 两个核心配置项的用法、参数参考与限制条件,并结合 http 适配器源码Http2Sessions 会话池 深入剖析其底层连接复用、空闲会话超时回收的实现机制,帮助你在 Node.js 服务中安全、高效地启用 HTTP/2 请求。

一、适用范围与启用前提

HTTP/2 支持是 Axios 1.13.0 版本加入 http 适配器的**实验性(experimental)**特性,当前仓库版本为 1.19.0,该功能持续可用但 API 仍可能在后续 minor 或 patch 版本中变动。关键限制如下:

  • 仅限 Node.js 环境:HTTP/2 依赖 Node.js 内置 http2 模块。从源码注释可以确认,Http2Sessions 是 Node-only 模块——浏览器/React Native 构建会通过 package.jsonbrowser 字段把唯一的导入方 lib/adapters/http.js 替换为 lib/helpers/null.js,因此这些环境永远不会触及 HTTP/2 路径;
  • 不支持代理:显式配置 Axios proxy 对象后发起 httpVersion: 2 请求会直接抛出 ERR_NOT_SUPPORT(见下文源码分析);
  • 不跟随重定向:HTTP/2 传输不会自动跟随 3xx 响应,需要手动处理或对该类端点保持 HTTP/1.x。

二、基本用法:httpVersion 选项

使用请求配置中的 httpVersion 选项选择协议版本,设为 2 即启用 HTTP/2:

const { data, headers, status } = await axios.post(
  "https://httpbin.org/post",
  form,
  {
    httpVersion: 2,
  },
);

httpVersion每请求生效的选项,默认值为 1。从 TypeScript 类型声明 可以看到其合法取值仅为 1 | 2

httpVersion?: 1 | 2;
http2Options?: Record<string, any> & {
  sessionTimeout?: number;
};

源码中对 httpVersion 有严格校验:先做数值转换,若结果是 NaN 抛出 Invalid protocol version 错误,若不是 12 则抛出 Unsupported protocol version(见 lib/adapters/http.js 第 592-602 行):

httpVersion = +httpVersion;

if (Number.isNaN(httpVersion)) {
  throw TypeError(`Invalid protocol version: '${config.httpVersion}' is not a number`);
}

if (httpVersion !== 1 && httpVersion !== 2) {
  throw TypeError(`Unsupported protocol version '${httpVersion}'`);
}

const isHttp2 = httpVersion === 2;

配置合并遵循 Axios 的标准实例级/请求级覆盖规则:实例级 httpVersion: 2 可以被单请求的 httpVersion: 1 覆盖,smoke 测试 对此有专门验证。

三、http2Options:透传原生选项与 sessionTimeout

内部 session.request() 调用的额外原生选项可通过配置对象 http2Options 传入。其中包含一个 Axios 自定义参数 sessionTimeout,控制空闲 HTTP/2 会话在被关闭前保持存活的时间(毫秒),默认值为 1000ms

{
  httpVersion: 2,
  http2Options: {
    rejectUnauthorized: false, // 接受自签名证书(仅限开发环境)
    sessionTimeout: 5000,      // 空闲会话保持 5 秒后关闭
  },
}

sessionTimeout 外,Node.js 内置 http2 模块支持的所有原生 session.request() 选项(如 rejectUnauthorizedmaxSessionHeaderslookup 等)都可以放在 http2Options 中透传。实例级与请求级的 http2Options 会进行合并(请求级键覆盖实例级同名键),smoke 测试 验证了如下合并行为:

// 实例级: { rejectUnauthorized: false, sessionTimeout: 1000 }
// 请求级: { sessionTimeout: 5000, customFlag: true }
// 合并结果: { rejectUnauthorized: false, sessionTimeout: 5000, customFlag: true }

配置参考

选项 类型 默认值 说明
httpVersion number 1 使用的 HTTP 协议版本。设为 2 启用 HTTP/2。
http2Options.sessionTimeout number 1000 空闲 HTTP/2 会话被关闭前的存活时间(毫秒)。

其余所有 Node.js http2 模块支持的原生 session.request() 选项均可通过 http2Options 传入。

四、完整示例:multipart 上传 + 双向进度监听

以下示例通过 HTTP/2 发送 multipart/form-data POST 请求,同时监听上传与下载进度:

const form = new FormData();
form.append("foo", "123");

const { data, headers, status } = await axios.post(
  "https://httpbin.org/post",
  form,
  {
    httpVersion: 2,
    http2Options: {
      // rejectUnauthorized: false,
      // sessionTimeout: 1000
    },
    onUploadProgress(e) {
      console.log("upload progress", e);
    },
    onDownloadProgress(e) {
      console.log("download progress", e);
    },
    responseType: "arraybuffer",
  },
);

该示例覆盖了 HTTP/2 传输的几个典型场景:FormData 流式上传、onUploadProgress/onDownloadProgress 事件回调、responseType: "arraybuffer" 二进制响应处理。

五、源码剖析:HTTP/2 请求是如何发出的

5.1 http2Transport:会话池与请求发起

lib/adapters/http.js 中定义了 HTTP/2 专属传输 http2Transport。当 isHttp2 为真时,适配器会选用该传输(而非 follow-redirects 的 httpFollow/httpsFollow):

const http2Transport = {
  request(options, cb) {
    const authority =
      options.protocol +
      '//' +
      options.hostname +
      ':' +
      (options.port || (options.protocol === 'https:' ? 443 : 80));

    const { http2Options, headers } = options;

    const session = http2Sessions.getSession(authority, http2Options);

    const { HTTP2_HEADER_SCHEME, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_STATUS } =
      http2.constants;

    const http2Headers = {
      [HTTP2_HEADER_SCHEME]: options.protocol.replace(':', ''),
      [HTTP2_HEADER_METHOD]: options.method,
      [HTTP2_HEADER_PATH]: options.path,
    };

    utils.forEach(headers, (header, name) => {
      name.charAt(0) !== ':' && (http2Headers[name] = header);
    });

    const req = session.request(http2Headers);

    req.once('response', (responseHeaders) => {
      const response = req; //duplex
      responseHeaders = Object.assign({}, responseHeaders);
      const status = responseHeaders[HTTP2_HEADER_STATUS];
      delete responseHeaders[HTTP2_HEADER_STATUS];
      response.headers = responseHeaders;
      response.statusCode = +status;
      cb(response);
    });

    return req;
  },
};

从源码结构看,这里有几个值得注意的细节:

  1. 按 authority(协议 + 主机 + 端口)复用会话authority 形如 https://example.com:443,同一 authority 且 http2Options 完全相同的请求会复用同一个 http2.connect() 会话;
  2. 伪头处理:HTTP/2 要求 :scheme:method:path 伪头,适配器自动从 options 构造;用户传入的以 : 开头的头会被显式跳过,避免污染伪头;
  3. 状态码提取:HTTP/2 响应头中的 :status 伪头被取出并转换为数字 statusCode,其余头部原样透传为 response.headers

这正是文档中"HTTP/2 不跟随重定向"警告的根源——HTTP/1 路径走 follow-redirects 传输可以自动跟随 3xx,而 http2Transport 收到响应头后立即回调,3xx 状态码会原样暴露给调用方。

5.2 Http2Sessions:连接池与空闲超时回收

lib/helpers/Http2Sessions.js 是会话池的核心实现。其 getSession(authority, options) 方法(第 16-42 行):

  • sessionTimeout: 1000 作为默认值注入 options
  • 遍历该 authority 已缓存的会话,仅当会话未被销毁、未关闭,且其创建选项与本次 options 通过 util.isDeepStrictEqual 深度相等时才复用——这意味着如果你在下一次请求中改变了 http2Options(哪怕只改一个字段),会新建一个独立会话,而不是复用旧的;
  • 否则调用 http2.connect(authority, options) 建立新会话并缓存。

空闲超时逻辑(第 80-106 行)通过包装 session.request 实现:

const { sessionTimeout } = options;

if (sessionTimeout != null) {
  let streamsCount = 0;

  session.request = function () {
    const stream = originalRequestFn.apply(this, arguments);

    streamsCount++;

    if (timer) {
      clearTimeout(timer);
      timer = null;
    }

    stream.once('close', () => {
      if (!--streamsCount) {
        timer = setTimeout(() => {
          timer = null;
          removeSession();
        }, sessionTimeout);
      }
    });

    return stream;
  };
}

机制可以概括为:每次发起请求时取消待触发的关闭定时器并累加活跃流计数;当最后一个流 close 后启动 sessionTimeout 毫秒的定时器,到期仍未有新请求就关闭并从池中移除该会话。若 sessionTimeout 设为 null/undefined(显式传入),则不做空闲回收,会话常驻至 close/error 事件触发 removeSession第 108-109 行)。removeSession 同时处理了定时器清理、会话从 authority 数组中摘除和 session.close() 调用,且做了幂等保护。

5.3 代理、DNS lookup 与特殊约束

  • 代理互斥lib/adapters/http.js 第 1012-1023 行 中,若请求应用了 proxy 且 isHttp2 为真,直接以 HTTP/2 requests with a proxy are not supported 拒绝(ERR_NOT_SUPPORT)。源码注释说明:HTTP/2 传输独立于 HTTP/1 agent 建立连接,无法应用 axios 解析出的代理或 agent 的环境代理,因此显式 proxy 配置被显式拒绝。proxy: false 则继续强制直连;
  • 自定义 DNS lookup 透传第 925-927 行 中,若配置了 lookup,HTTP/2 请求会将其注入 http2Options,使自定义解析函数同样作用于 HTTP/2 连接,且因 options 深度比较一致仍能安全复用池化会话:
if (isHttp2 && lookup) {
  http2Options = Object.assign(Object.create(null), http2Options, { lookup });
}

六、实践建议

  1. 实验性定位:HTTP/2 API 仍标注 experimental,升级 Axios 版本时建议关注变更日志中 "HTTP/2" 相关条目;
  2. 重定向敏感端点:依赖服务端 3xx 跳转的业务保持 httpVersion: 1(或不设置),或自行捕获 3xx 并手动发起新请求;
  3. sessionTimeout 调优:默认 1000ms 偏激进,请求间隔超过 1 秒就会重建连接。对高频调用同一 authority 的场景,可适当调大(如 5000-10000ms)以获得连接复用的收益;
  4. 保持 http2Options 稳定:由于会话复用要求选项深度相等,频繁变化的 http2Options 会导致会话池碎片化、连接数上升;
  5. 开发环境自签名证书rejectUnauthorized: false 仅在开发环境使用,生产环境勿开。

七、测试验证

tests/smoke/cjs/tests/http2.smoke.test.cjs(及 esm 版本)对配置传递做了三类断言,可作为行为契约参考:

  1. 实例级 httpVersionhttp2Options 完整保留在请求 config 中;
  2. 请求级 http2Options 与实例级正确合并(同名键请求级胜出);
  3. 请求级 httpVersion 可覆盖实例级设置。

配合 Http2Sessions 单元测试http 适配器测试,你可以在本地运行 smoke 测试套件验证 HTTP/2 相关行为是否符合预期。

小结

Axios 的 HTTP/2 支持通过 httpVersion: 2 一行配置即可在 Node.js 中启用,http2Options 则提供了原生 http2 选项透传与 sessionTimeout 空闲回收控制。理解其底层的 authority 会话池、选项深度相等复用规则和 1000ms 默认空闲超时,能让你在连接复用、资源释放与重定向/代理限制之间做出正确的工程权衡。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.79 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
988
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384