can do

*experimental

*

#SeattleJS

Trivikram Kamat

Software Development Engineer

@trivikram

@trivikr

Tree

Weak

Rum

+

+

Tri

vik

ram

.

.

What's your name again?

My history with Node.js

  • Have been using Node.js for almost 4 years

  • Started contributing to Node.js core in Oct 2017

    • providing HTTP/2 support

  • Became Node.js core collaborator in March 2018

What are we going to cover?

  • What's HTTP/1.1, and why HTTP/2 was required

  • What's HTTP/2, and why HTTP/3 was required

  • What's HTTP/3, and 

  • Sample code!

when is it coming?

James Snell

is a Node.js TSC member, who is heading the work on implementing QUIC

Big Thanks to sponsors:

Internet and www

Naah!

You know what's Internet and www

Let's jump into HTTP/1.1

HTTP/1.1

Published: June 1999

Issue with HTTP/1.1

Multiple TCP+TLS connections for concurrent requests 

http/1.1 server

const https = require("https");
const fs = require("fs");

const options = {
  key: fs.readFileSync("ssl/localhost.key"),
  cert: fs.readFileSync("ssl/localhost.cert")
};

https
  .createServer(options, (req, res) => {
    if (req.url === "/") {
      fs.createReadStream("./files/index.html").pipe(res);
    } else if (req.url === "/style.css") {
      fs.createReadStream("./files/style.css").pipe(res);
    } else if (req.url === "/script.js") {
      fs.createReadStream("./files/script.js").pipe(res);
    } else if (req.url === "/globe.png") {
      fs.createReadStream("./files/globe.png").pipe(res);
    }
  })
  .listen(3000);

index.html

<html>
  <head>
    <link rel="stylesheet" type="text/css"
          href="./style.css" />
  </head>
  <body>
    <span id="hello">Hello World!</span>
    <img src="./globe.png" />
    <script type="text/javascript" 
            src="./script.js"></script>
  </body>
</html>

style.css

#hello {
  font-size: 100px;
}

script.js

setTimeout(() => {
  const helloDiv = 
    document.getElementById("hello");
  helloDiv.innerHTML = 
    "Hello SeattleJS!";
}, 1000);

globe.png

Load the webpage

examine TCP connections with netstat

$> watch 'netstat -t | grep localhost'

Issues with HTTP/1.1

  • Three round-trips per request

  • Multiple TCP+TLS connections for concurrent requests

HTTP/2

Published: May 2015

http/2 server

const http2 = require("http2");
const fs = require("fs");

const options = {
  key: fs.readFileSync("ssl/localhost.key"),
  cert: fs.readFileSync("ssl/localhost.cert")
};

const server = http2.createSecureServer(options).listen(3000);
server.on("stream", (stream, headers) => {
  if (headers[":path"] === "/") {
    stream.respondWithFile("./files/index.html");
  } else if (headers[":path"] === "/style.css") {
    stream.respondWithFile("./files/style.css");
  } else if (headers[":path"] === "/script.js") {
    stream.respondWithFile("./files/script.js");
  } else if (headers[":path"] === "/globe.png") {
    stream.respondWithFile("./files/globe.png");
  }
});

Load the webpage

examine TCP connections with netstat

$> watch 'netstat -t | grep localhost'

Benefits of HTTP/2

  • Multiplexing and concurrency: different HTTP requests onto the same TCP connection

  • Stream dependencies: client can indicate to server which dependencies are important

  • Header compression: reduces HTTP Header size

  • Server push: server can send resources which client has not requested yet

Why do we need HTTP/3?

TCP head-of-line blocking

If a single packet is dropped, or lost in the network somewhere between two endpoints that speak HTTP/2, it means the entire TCP connection is brought to a halt while the lost packet is re-transmitted and finds its way to the destination

Chain metaphor

TCP connection

CSS packet

JS packet

HTTP/3 over QUIC

draft-23 as of Oct 2019

When setting up multiple streams over QUIC connection, they are treated independently so that if any packet goes missing for one of the streams, only that stream has to pause and wait for the missing packet to get retransmitted.

CSS stream

JS stream

http/3 server

const quic = require("quic");
const fs = require("fs");

const options = {
  key: fs.readFileSync("ssl/localhost.key"),
  cert: fs.readFileSync("ssl/localhost.cert")
};

const socket = quic.createSocket({ port: 3000 });
socket.listen(options);
socket.on("session", session => {
  session.on("stream", (stream, headers) => {
    if (headers[":path"] === "/") {
      stream.respondWithFile("./files/index.html");
    } else if (headers[":path"] === "/style.css") {
      stream.respondWithFile("./files/style.css");
    } else if (headers[":path"] === "/script.js") {
      stream.respondWithFile("./files/script.js");
    } else if (headers[":path"] === "/globe.png") {
      stream.respondWithFile("./files/globe.png");
    }
  });
});

Load the webpage

HTTP/3 over QUIC in Node.js is in early stages of development

You can help build it!

But where can I contribute?

Start writing unit tests!

git clone git@github.com:trivikr/quic.git

cd quic

./configure --experimental-quic --coverage

make -j4 coverage

Current state of JavaScript tests

Current state of C++ tests

Example webpage on QUIC

Summary

  • In HTTP/1.1, multiple TCP+TLS connections were required for concurrent requests

  • HTTP/2 added multiplexing in which multiple HTTP requests were sent onto the same TCP connection

  • TCP head-of-line blocking: the entire TCP connection is brought to halt if a single TCP packet is lost.

  • HTTP/3 over QUIC treats each stream independently, so if any packet goes missing in a stream - only that stream is affected

Thank you for listening!

Trivikram Kamat

@trivikram

@trivikr

HTTP/3: Node.js can do QUIC

By Trivikram Kamat

HTTP/3: Node.js can do QUIC

Slides for SeattleJS meetup talk in October 2019 https://www.meetup.com/seattlejs/events/clmbzqyznbnb/

  • 2,165