Http/2

"Connection management is a key topic in HTTP". This is how MDN begins its story of raising HTTP/2. Starting from the naive short-lived connections through keep-alive connections and the HTTP/1.1 pipeline, the story ends with a new protocol - HTTP/2 and the newest HTTP/3. All this is around the HOL blocking problem, the same issue as in a regular FIFO queue - some element in the queue (in our case this element is a request) may require a long time to be processed, and all consequences elements are standing in wait.

The last HTTP/1.1 attempt to fight the connection management was pipelining. The technique uses the same TCP connection to send multiple HTTP requests without waiting for the corresponding responses. But even the HTTP/1.1 pipeline is subject to the HOL problem because the responses were sent back in order.

HTTP/1.1 pipeline processing is initiated by setting the "Keep-Alive" HTTP header in addition to "Connection" (that alone usually initiates a Persistent connection).

GET /index.html HTTP/1.1
Connection: Upgrade, Keep-Alive
Keep-Alive: timeout=5, max=100
Content-Type: text/html; charset=UTF-8

To move step forward from here we need to realize that that main performance bottleneck in the picture above is the order - the responses need to be read in the same order as they written to the connection. Hence, the HOL issue.

The order may be combated by the streaming: let's imagine that each request/response expoits its own stream of data. Firstly for request's data and then when the response it ready (even partly) for the output data.

Define the frame (stream) as following:

    +-----------------------------------------------+
    |                 Length (24)                   |
    +---------------+---------------+---------------+
    |   Type (8)    |   Flags (8)   |
    +-+-------------+---------------+-------------------------------+
    |R|                 Stream Identifier (31)                      |
    +=+=============================================================+
    |                   Frame Payload (0...)                      ...
    +---------------------------------------------------------------+

Possible values for Type - DATA(0), HEADERS(1), RST_STREAM(3), SETTINGS(4), WINDOW_UPDATE(8)

For example, consider the following WireShart dissertion:

The selected packet is marked as GRPC protocol (after context menu "Decode as...")

And now let's look at "Packet Details" and "Packet Bytes" panes. We can observer four HTTP/2 segments (frames) here: MAGIC, SETTINGS, HEADERS and DATA.

MAGIC is a special case - it is only contains the special sequence ("PRI * HTTP/2 ...") and used for initiate the HTTP/2 conversation

SETTINGS (Type=4) frame is obey the mentined structure, but its length is 0 rather as flags and stream identifier

HEADERS (Type=1) frame is fully obeyed frame. In our example it has the flags = End Stream) and the identifier (=1) followed by pseudo-headers (started with semicolns, : - :authority, :method, :path: /oauth2/OtpProcessor/StreamTime and :scheme) and natural headers (grpc-accept-encoding, content-type: application/grpc etc.)

DATA (Type=0) - full frame containing stream (=1) and small (5 bytes) data payload

gRPC over HTTP/2