🧊

A QUIC bit of fun with Node.js - James Snell の要点まとめ

YouTube

NodeConf EU 2019でのトークの要点まとめです。

はじめに

  • NearForm社でリサーチやってます
  • 主にOSS活動
  • 最近はNodeにQUICを実装してる

HTTP/2 in Node.js

  • その前にHTTP/2について
  • Nodeにも実装はあって、2017年にコアにはいった
    • けど、残念ながら使い勝手はあまりよくない...
  • だいたいのNodeは前段にNginxなどを置くせい
  • HTTP/2はステートフルなプロトコル
    • ヘッダ圧縮のために、コネクションは状態を持つ必要がある
    • それを経由するミドルボックスで協調してメンテするのが無理
  • Node <-> Nodeとか、ブラウザ直でつなげるなら有用ともいえる

HTTP/2

  • HTTP/1.xは、1リクエスト:1TCPコネクション
  • なのでHOLBが問題になる
    • 1つパケットが落ちると、後続のパケットはその再送を待つ
  • HTTP/2では、リクエストを多重化した
    • Nリクエスト:1TCPコネクション
  • しかし結局TCPなので、HOLBからは逃れられない...
  • 物理的に距離が遠かったり、モバイルなど低品質のNWの場合にそれが顕著

QUIC

  • そこでQUIC, HTTP/3
  • QUICはUDPベース
    • unreliableなプロトコル
    • それぞれのパケットは独立してる
  • なのでTCPでやってたことを、全部実装しなおしてる
    • 到達確認(=reliable)
    • シーケンス(=ordering)
    • 輻輳制御
    • 暗号化 w/ TLS1.3
    • etc...
  • HTTP/3は、そんなQUICセッションを束ねてる
  • TCPはIPに紐付いたコネクションなので、NWを変えると切れる
    • そういうのも大丈夫

QUIC in Node.js

const { createSocket } = require("quic");
const socket = createSocket();

socket.listen({ port: 443, key, cert, ca });

socket.on("session", session => {
  session.on("stream", stream => {
    stream.end("Hello world!");
  });
});
  • ただいま絶賛実装中
  • という具合に、見慣れたNodeのコードで書ける
    • `stream`は単なる`Duplex`な`Stream`
  • そしてQUICは単なるトランスポートプロトコル
const { createSocket } = require("quic");
const socket = createSocket();

const req = socket.connect({ address, port: 443, key, cert, ca });

req.on("secure", () => {
  const stream = req.openStream();  
  stream.end("Hello world!");
  stream.on("data", data => {});
});
  • という感じでHTTP/3を実装する
  • なのでQUICの上に独自のプロトコルを実装することもできる

進捗

  • `ngtcp2`の`tatsuhiro-t`さんありがとう
  • 実装はここで進行中
  • おそらく2019年の11月末にExperimentalなPRをコアに出せそう
    • ただし来年いっぱいくらいはAPIを洗練したり検討したりすると思う
    • まだ実装しないといけないこともいっぱいあるし
  • (クラサバでパケットを送り合うデモ)
    • 流れたByte数とかストリームの数などが、JSのAPIから取れる!
  • Wiresharkとかでデバッグできるようキーロギングサポートも