Node.js 对 HTTP/3 的支持进展

论坛 期权论坛 期权     
Node地下铁   2019-7-29 01:09   3918   0
当我们打开 chrome DevTools 查看 Network 的时候,可能偶尔会看到夹杂在 HTTP/1.1,HTTP/2.0 之外的一些协议比如,http/2 + quic/43。

quic 是什么?




QUIC 最早是由 Jim Roskind 在 Google 设计并于 2012 年实现的一个基于 UDP 的绑定 HTTP 场景的协议(send-http/2-frames-over-udp),并于 2015 年 提交到 IETF 进行标准化.  IETF 于 2016 年成立的 QUIC 工作组把 QUIC 定位为一个传输层协议(需要支持 HTTP 以外的其它应用层协议),而把 QUIC 到 HTTP 语义的映射独立为 HTTP over QUIC 层。2018 年 11 月, IETF 决定把  HTTP over QUIC 命名为 HTTP/3。




HTTP/3 相较于 HTTP/2 的显著优势包括:

  • 基于 UDP 而带来的队头阻塞(Head of line Blocking)优化。虽然 HTTP/2 通过多路复用部分缓解了队头阻塞,但受限于 TCP 的顺序处理,在容易丢包的弱网环境下,HTTP/2 的队头阻塞比 HTTP/1.1 更严重。
  • 基于 UDP 而带来的连接迁移能力。连接可以在 IP 地址和网络接口迁移的情况下得到保持,e.g. Wi-Fi 到蜂窝或者反之。
  • 基于 QUIC 实现带来的往返时延(RTT)优化。
  • 在用户空间实现流量控制带来的协议升级便利。TCP 协议实现在内核协议栈,协议升级需要设备系统升级,成本巨大,通常会产生协议僵化。

HTTP/3 标准目前处于 draft 22 阶段,实现还不多,已知的浏览器都还没有支持。Google QUIC 虽然已经兼容了 IETF QUIC draft 22,但还不支持 IETF HTTP over QUIC。如果用 wireshark 分析 youtube 的 http/2+quic/43 的请求,会把它识别为 GQUIC 协议而不是标准的 IETF QUIC。




Node.js 官方对 HTTP/3 支持的进展目前还处于实现传输层协议 QUIC 的阶段。你可以尝试自己编译 nodejs/quic 来体验一下。

> git clone https://github.com/nodejs/quic.git> cd quic> ./configure> make -j4# 查看编译产生的 Node.js 版本> ./out/Release/node --versionv13.0.0-pre
编写你的体验代码

// 在当前目录下准备好证书和秘钥,比如:// openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \  -keyout localhost-privkey.pem -out localhost-cert.pemconst { createSocket } = require('quic');const fs = require('fs');const key = fs.readFileSync('localhost-privkey.pem');const cert = fs.readFileSync('localhost-cert.pem');const { debuglog } = require('util');const debug = debuglog('7n');const ServerPort = 12265;const ClientPort = 12266;const server = createSocket({    port: ServerPort,    type: 'udp4'});server.listen({    key, cert});server.on('session', (session) => {    debug('QuicServerSession created');    session.on('secure', () => {        debug('QuicServerSession TLS Handshake Completed.');    });    session.on('stream', stream => {        debug('Client Stream Received.');        debug(`Client-initiated stream id: ${stream.id}; bidirectional: ${stream.bidirectional}, unidirectional: ${stream.unidirectional}`);        stream.on('end', () => {            console.log(`~~~ Client-initiated stream id: ${stream.id} on end`);        });        stream.on('data', data => {            console.log(`~~~ Client-initiated stream id: ${stream.id} on data: ${data}`);        });    });});server.on('ready', () => {    debug('Server Ready');});server.on('listening', () => {    debug('Server listening on port %d', server.address.port);    const client = createSocket({        port: ClientPort,        type: 'udp4'    });    const req = client.connect({        type: 'udp4',        address: 'localhost',        port: ServerPort,        rejectUnauthorized: false,        maxStreamsUni: 10,    });    req.on('secure', () => {        debug('QuicClientSession TLS Handshake Completed');        const bidi = req.openStream({ halfOpen: false });        bidi.end('Hello World');    });});
运行一下试试。

> ./out/Release/node 7n.js7N 57222: Server Ready7N 57222: Server listening on port 122657N 57222: QuicServerSession created7N 57222: QuicClientSession TLS Handshake Completed7N 57222: QuicServerSession TLS Handshake Completed.7N 57222: Client Stream Received.7N 57222: Client-initiated stream id: 0; bidirectional: true, unidirectional: false~~~ Client-initiated stream id: 0 on data: Hello World~~~ Client-initiated stream id: 0 on end
如果用 wireshark 分析,会看到 wireshark 识别出了 IETF QUIC 协议。



相比较于 Node.js 还在实现传输层协议。另一个 Node.js 三方库 quicker 的完成度要高得多。它不仅实现了 QUIC 协议,还提供了 HTTP over QUIC(HTTP/3) 以及 HTTP/3 QPACK 的实现,因此,你可以通过它的 client 使用 HTTP 方式发起请求(目前只支持 GET)。

> node /quicker/out/http/http3/client/democlient.js 127.0.0.1 4433
但这里的 node 也是一个定制过的 Node.js 运行时(可以使用作者提供的 docker 体验),后续要适配 Node.js 的升级也有不小的成本。等 Node.js 官方交付 quic 实现之后,上层的 HTTP/3 client 会有更快速的发展。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:25
帖子:5
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP