The evolution of Internet Protocols: Why QUIC is the next big thing.
What is QUIC? How did we arrive here?
What is QUIC? How did we arrive here?
As with most of my posts, let me start off with a history lesson and build this brick by brick so that we appreciate where we are.
HTTP 1 : The Grandaddy
We started off with HTTP/1.0 where each request-response pair was preceded by an opening of a tcp connection followed by a closing of the same connection. This introduced a lot of latency and caused people to work to come up with a workaround called keep-alive which reuses the TCP connection across HTTP requests essentially delaying closing the connection. Below are two diagrams with and without keep-alive.
This example also demonstrates the TCP 3 way handshake that needs to be established before making an HTTP request. Essentially both parties keep track of what they have sent using a sequence number (SYN packet). So that if they lose any packets they can just retransmit from the last sequence number. Note the 3 way handshake (SYN,SYN-ACK,ACK) which needs to be done as part of each connection establishment. As TCP is a bi directional mode of communication, you need ACKs in each direction.FIN is used to close the TCP connection.
Keep-alive looks fine; won’t you say?
Look closely, each resource request still needs its previous resource request to be completed before firing. For example I cannot fire a request for index.css before index.html has returned.
Hmm.. How did they fix this?
They introduced a feature called pipelining in HTTP/1.1. With this feature, each HTTP request over the TCP connection may be made immediately without waiting for the previous request’s response to return. The diagram shows HTTP/1.1. with pipelining.
What’s broken?
The responses will come back in the same order. This introduces an issue called HTTP Head of Line (HOL) Blocking
What’s HOL blocking?
Let’s say you are making a request for an cat image(cannot get enough of cats) and a javascript file. If the image is of a large size the server will not start sending the javascript file until it has finished sending the image.
Arghhhh!!! That sounds terrible. How was that fixed.
The initial approach was to have the browser open up to 6 connections to the same server and as a performance optimization developers started sharding the resources across multiple domains to support the case of more than 6 resources on the server. Also this did not solve the overhead of setting up the TCP (and TLS. I am refraining discussing TLS till part 2) handshakes for each individual connection.
This also introduced innovations like css image sprites reducing the number of individual resources to be transferred over the wire.
Soon people realised this won’t scale and a new approach was introduced which became HTTP/2 with multiplexing.
Essentially it states that each HTTP request over the TCP connection may be made immediately without waiting for the previous response to come back. The responses may come back in any order. Again below diagrams illustrate HTTP/1.1 pipelining and HTTP/2 multiplexing using streams. Note how in HTTP/2 using multiplexed streams the view.css is returned before the cat.png
Also unlike in HTTP/1.1 where the resource identification as part of the HTTP header in only the first tcp packet of a group of tcp packets, in HTTP/2 each TCP packet contains the identification of the resource. This allows HTTP responses which are split into multiple TCP packets to be easily reassembled eliminating the serial nature of HTTP/1.1
Yeah, looks like we have maxed out on improvements with HTTP/2 multiplexing
Not quite, there is one more flaw here, but you have to look a level deeper into the TCP stack.
Uh oh, What is the flaw now?
TCP is a connection oriented protocol. It keeps a track of all packets that have been transmitted between client and server, if a packet is lost in transit from the server it will hold all the packets post that packet’s sequence number and not pass them to the application layer until the missing packet is retransmitted. Here is a diagram to illustrate the same.
For example in the diagram if packet 2 from view.css is lost, it causes all the packets from 3–20 to be stored in the receive buffer and not passed up to the application stack until packet 2 has been retransmitted. Even though all the packets from cat.png would have been received, the underlying TCP protocol has no way of knowing the same so it forces a retransmission.
(Note This diagram is not a very accurate representation as I have switched from a HTTP response to a TCP response to illustrate the problem).
So what do we do now Sensei? :-)
The underlying problem if you look at it closely is because of the underlying connection oriented nature of TCP. For example if TCP knew that packet 1 and packet 2 are part of view.css it would cause just packet 2 to be retransmitted and not block packets 3–20. The stream ids which identify the underlying multiplexed streams in the HTTP/2 layer are disconnected from the underlying TCP packet ids.
I know of an alternative called UDP which is connection less.
But we still need connections don’t we? How do we request for resources in a reliable manner (Retransmissions, acks, sequencing and the whole shabang. ) without a connection. We need a way to identify resources across multiple TCP packets.
What if we remove TCP and use a streaming protocol over IP and layer it with HTTP? This protocol will maintain a single connection as before but streams will have their own retransmissions. In effect each stream will have tcp characteristics over a single larger connection.
That’s exactly what HTTP/3 over QUIC does. QUIC as a replacement to TCP maintains streams on top of the underlying UDP packets itself and HTTP/3 in contrast to HTTP/2 knows nothing about streams. Think of the streams as mini TCP connections but at a resource level. Put in another way, QUIC retains ordering within a single resource stream but no longer across individual streams as compared to HTTP. It also means that QUIC no longer passes resources to the application layer in the same order it was requested.
Any other advantages?
Another goal of the QUIC system was to improve performance during network-switch events, like what happens when a user of a mobile device moves from a local wifi hotspot to a mobile network. When this occurs on TCP, a lengthy process starts where every existing connection times out one-by-one and is then re-established on demand. To solve this problem, QUIC includes a connection identifier which uniquely identifies the connection to the server regardless of source. This allows the connection to be re-established simply by sending a packet, which always contains this ID, as the original connection ID will still be valid even if the user’s IP address changes.
Flow control which indicates how fast the client and server can go is maintained at a stream level. This works by publishing/advertising a window which indicates how much more data each side can send and updating that after every successful transmission.
To recover from lost packets without waiting for retransmission, QUIC can complement a group of packets with an FEC packet. Much like RAID-4, the FEC packet contains parity of the packets in the FEC group. If one of the packets in the group is lost, the contents of that packet can be recovered from the FEC packet and the remaining packets in the group. The sender may decide whether to send FEC packets to optimize specific scenarios (e.g., beginning and end of a request).
Hmm. Why do we need UDP? Why not QUIC over IP?
That’s because most of the firewalls on the enterprise and internet still support UDP as a protocol. If we were to layer QUIC over IP, we would have to reconfigure all of them. UDP is a small overhead anyways (8 byte header) .
So are we done? What about security?
Aha!! Excellent question Padawan. I have deliberate skirted over TLS. Let’s run through it in the next part.
Credits
https://en.m.wikipedia.org/wiki/QUIC
Head-of-Line Blocking in QUIC and HTTP/3: The Details
Head-of-Line Blocking in QUIC and HTTP/3: The Details As you may have heard, after 4 years of work, the new HTTP/3 and…calendar.perfplanet.com