A Detailed Explanation of HTTP/3

Head-of-Line Blocking in HTTP/2

Although HTTP/2 uses “frames”, “streams”, and “multiplexing” to eliminate “head-of-line blocking”, these techniques are applied at the application layer. However, at the lower layer, specifically in the TCP protocol, “head-of-line blocking” can still occur.

TCP has a special “packet retransmission” mechanism to ensure reliable transmission. Lost packets must wait for retransmission confirmation, and other packets, even if received, can only be held in a buffer, leaving the upper layer applications unable to access them, which can be quite frustrating.

For example, if a client sends three packets using TCP, but the operating system on the server only receives the last two packets while the first packet is lost, the TCP stack in the kernel can only temporarily store the received packets and “pause” until the client retransmits the lost packet, resulting in “head-of-line blocking” again.

Since this “head-of-line blocking” is inherent to the TCP protocol, no matter how many “tricks” HTTP/2 designs, it cannot resolve this issue.

Google recognized this problem when promoting SPDY, which led to the invention of a new protocol called “QUIC” that allows HTTP to run over QUIC instead of TCP.

Thus, “HTTP over QUIC” represents the next major version of the HTTP protocol, HTTP/3. It achieves a qualitative leap over HTTP/2, effectively and perfectly solving the “head-of-line blocking” problem.

A Detailed Explanation of HTTP/3

QUIC Protocol

QUIC selects UDP and incorporates TCP’s connection management, congestion window, flow control, and other features, “discarding the dross and selecting the essence” to create a brand new reliable transport protocol, which can be considered the “TCP of the new era”.

QUIC was originally invented by Google and is referred to as gQUIC. The version currently being standardized by the IETF is called iQUIC. The differences between the two are significant, even greater than the differences between SPDY and HTTP/2.

gQUIC combines UDP, TLS, and HTTP into an application layer protocol. The IETF has “cleaned up” gQUIC by separating the application portion, forming HTTP/3, while the original UDP portion has been “delegated” to the transport layer, which is why iQUIC is sometimes referred to as “QUIC-transport”.

From now on, when we refer to QUIC, we mean iQUIC, which is a transport layer protocol and operates at the same level as TCP.

Features of QUIC

QUIC is based on UDP, which is “connectionless” and does not require “handshakes” or “teardowns”, making it inherently faster than TCP.

Just as TCP achieves reliable transmission over IP, QUIC also implements reliable transmission over UDP, ensuring that data can reach its destination. It introduces features similar to HTTP/2’s “streams” and “multiplexing”. Each individual “stream” is ordered and may be blocked due to packet loss, but other “streams” remain unaffected.

To prevent intermediate devices on the network (Middle Box) from recognizing protocol details, QUIC employs comprehensive encrypted communication, effectively resisting tampering and “protocol ossification”.

Moreover, since TLS 1.3 was officially released last year (2018), QUIC directly utilizes TLS 1.3, thereby benefiting from 0-RTT and 1-RTT connections.

However, QUIC is not built on top of TLS; instead, it “contains” TLS internally. It uses its own frames to “take over” the “records” in TLS, and handshake messages and alert messages do not use TLS records but are directly encapsulated into QUIC frames for transmission, eliminating one round of overhead.

Internal Details of QUIC

The basic data transmission units in QUIC are packets and frames, where a packet consists of multiple frames. Packets are oriented towards “connections”, while frames are oriented towards “streams”.

QUIC uses opaque “connection IDs” to mark the two endpoints of communication, allowing clients and servers to choose a set of IDs to identify themselves. This removes the strong binding of connections to “IP address + port” (the commonly referred to four-tuple) in TCP, supporting “connection migration”.

A Detailed Explanation of HTTP/3

For instance, when you return home from work, your phone automatically switches from 4G to WiFi. At this point, the IP address changes, and TCP must re-establish the connection. However, the connection IDs at both ends of the QUIC connection remain unchanged, so the connection is not “logically” interrupted and can continue using the previous connection on the new IP address, eliminating the cost of reconnection and achieving seamless connection migration.

QUIC frames come in various types, such as PING and ACK frames for connection management, while STREAM frames are specifically used for implementing streams.

The streams in QUIC are very similar to those in HTTP/2, being sequences of frames. However, while streams in HTTP/2 are all bidirectional, QUIC distinguishes between bidirectional streams and unidirectional streams.

A Detailed Explanation of HTTP/3

QUIC frames generally use variable-length encoding, requiring a minimum of 1 byte and a maximum of 8 bytes. The maximum available bits for stream IDs is 62, significantly increasing the number compared to HTTP/2’s 2^31.

The stream ID also reserves the lowest two bits for flags: the first bit indicates the stream initiator (0 for client, 1 for server), and the second bit indicates the stream direction (0 for bidirectional stream, 1 for unidirectional stream).

Thus, the odd-even nature of QUIC stream IDs is exactly the opposite of HTTP/2, with client IDs being even and starting from 0.

HTTP/3 Protocol

Since QUIC already supports encryption, streams, and multiplexing, the workload for HTTP/3 has been significantly reduced, delegating stream control to QUIC. The calls are no longer to TLS’s security interfaces or Socket APIs, but to dedicated QUIC functions. However, these “QUIC functions” have not yet formed a standard and must be bound to a specific implementation library.

HTTP/3 still uses streams to send “request-response” pairs, but it does not need to define streams like HTTP/2; instead, it directly uses QUIC’s streams, effectively creating a “conceptual mapping”.

The “bidirectional streams” in HTTP/3 can fully correspond to the streams in HTTP/2, while the “unidirectional streams” are used for control and push in HTTP/3, roughly corresponding to HTTP/2’s stream 0.

With stream management delegated to QUIC, the structure of frames in HTTP/3 has also simplified.

The frame header contains only two fields: type and length, both of which also use variable-length encoding, requiring a minimum of two bytes.

A Detailed Explanation of HTTP/3

Frames in HTTP/3 are still divided into data frames and control frames, with HEADERS frames and DATA frames used for data transmission. However, some other frames have disappeared in HTTP/3 because they have been replaced by lower-level QUIC frames, such as RST_STREAM, WINDOW_UPDATE, PING, etc.

The header compression algorithm in HTTP/3 has been upgraded to “QPACK”, with changes in its usage. Although it is still divided into static and dynamic tables, when sending HEADERS frames over streams, fields cannot be updated but can only be referenced. Updates to the index table must be sent via dedicated unidirectional streams, resolving the “head-of-line blocking” issue present in HPACK.

Additionally, the QPACK dictionary has been optimized, increasing the static table from 61 to 98 entries, with the numbering starting from 0, meaning that the number for “:authority” is 0.

HTTP/3 Service Discovery

HTTP/3 does not specify a default port number, meaning it does not necessarily have to provide HTTP/3 services on UDP port 80 or 443.

So, how can HTTP/3 be “discovered”?

This requires the use of the “extension frames” from HTTP/2. The browser needs to first connect to the server using the HTTP/2 protocol, and then the server can send an “Alt-Svc” frame after establishing the HTTP/2 connection, containing a string “h3=host:port”, informing the browser that equivalent HTTP/3 services are available at another endpoint.

Upon receiving the “Alt-Svc” frame, the browser will asynchronously connect to the specified port using QUIC. If the connection is successful, it will disconnect the HTTP/2 connection and switch to using HTTP/3 for data transmission.

Conclusion

A Detailed Explanation of HTTP/3

  1. HTTP/3 is based on the QUIC protocol, completely solving the “head-of-line blocking” problem, and performs better than HTTP/2 in weak network environments;
  2. QUIC is a new transport layer protocol built on UDP, achieving reliable transmission;
  3. QUIC incorporates TLS 1.3, enabling encrypted communication and supporting 0-RTT fast connection establishment;
  4. QUIC connections use “opaque” connection IDs that are not bound to “IP address + port”, supporting “connection migration”;
  5. QUIC streams are very similar to HTTP/2 streams but are divided into bidirectional and unidirectional streams;
  6. HTTP/3 does not specify a default port number and requires the use of the HTTP/2 extension frame “Alt-Svc” for discovery.

Leave a Comment