The labs on this site need JavaScript to run. The same content is written out below.
Learn › Networking › HTTP
HTTP/1.1, 2, 3
What differs between the versions when you fetch 30 files
A single web page is made of dozens of files (scripts, styles, images). HTTP/1.1 receives only one file at a time on a connection, so requests have to wait in line, while HTTP/2 mixes several requests on one connection. HTTP/3 changes even the transport layer below it.
Partly checked against real execution · HTTP/1.1 and 2 were checked with a browser; HTTP/3 and packet loss could not be reproduced
Concepts in this lab
- HTTP/1.1, HTTP/2, and HTTP/3
- HTTP/1.1 handles requests one at a time, in order, on a connection. HTTP/2 sends and receives several requests and responses at the same time over a single connection (multiplexing) and compresses headers. HTTP/3 uses the UDP-based QUIC protocol instead of TCP. This makes connection setup faster and reduces the problem where one lost packet also delays other requests.
- TCP and UDP
- The two main ways of transporting data on the internet. TCP establishes a connection before communication, guarantees that data arrives complete and in order, and sends data again if there is a problem. UDP sends data without a connection and does not guarantee arrival or order, but in return it is lightweight and fast. HTTP/1.1, HTTP/2, and database connections use TCP, and real-time video and voice and DNS mainly use UDP.
- Three-way handshake
- The three-step process used to establish a TCP connection. The client sends a connection request (SYN), the server sends its acceptance together with its own connection request (SYN+ACK), and the client acknowledges it (ACK). After both sides have confirmed that they can send to and receive from each other, data transfer starts.
Try these
- Default settings — HTTP/1.1. Six connections fetch six files at a time in five batches, so the requests wait in line four times.
- Switch to HTTP/2 — One connection fetches all 30 files at the same time.
- Packet loss with HTTP/2 — When one packet disappears, all the files stop together.
- Packet loss with HTTP/3 — Only the one file that the packet belongs to waits.
- HTTP/1.1, 60 files — The more files there are, the more times the requests wait in line.
Running with the default settings
- In HTTP/1.1, a connection has to receive the whole response to one request before it can send the next request. To go faster, the browser opens up to 6 connections to the same server. Each connection needs its own TCP and TLS handshakes.
- Batch #1: 6 connections receive one file each. The remaining 24 wait until a connection is free.
- Batch #2: 6 connections receive one file each. The remaining 18 wait until a connection is free.
- Batch #3: 6 connections receive one file each. The remaining 12 wait until a connection is free.
- Batch #4: 6 connections receive one file each. The remaining 6 wait until a connection is free.
- Batch #5: 6 connections receive one file each. No files are waiting now.
- All the files have been received. About 560ms in total.
Result of this run
- The files were received in 5 batches over 6 connections. The next request can be sent only after the earlier response is finished, so the more files there are, the longer the time spent waiting in line. That is why people used to use workarounds such as combining files into one or spreading them over several domains.
Code
# application.yml
server.http2.enabled: false # HTTP/2 (needs TLS)
# nginx
server {
listen 443 ssl;
...
}
<!-- Files requested by one page: 30 -->
Assumptions of this model
This is a model that assumes it takes 100ms to receive one file, 200ms to retransmit a lost packet, and, to set up the connection, 60ms for HTTP/1.1 (the 6 connections at the same time), 30ms for HTTP/2, and 20ms for HTTP/3. The real numbers depend on the network and the file sizes, and the 6 HTTP/1.1 connections that a browser opens to the same server is the default of the major browsers. The characteristics of each version follow the descriptions in the standards (RFC 9112, 9113, 9114). The part about the number of connections was checked in practice. In a real browser (Chromium-based), 18 requests that each take 0.3s were sent at the same time to an HTTP/1.1 server, and they were handled on 6 connections, at most 6 at a time, which took 931ms; with HTTP/2 (the built-in Node implementation), 30 requests were handled at the same time on 1 TCP connection and finished in 324ms. The difference when a packet is lost, and HTTP/3, could not be reproduced on the PC used to write this lab.
Previous lab: HTTP messages and status codes · Next lab: Cookies