# Http/2

"Connection management is a key topic in HTTP". This is how MDN [begins](https://developer.mozilla.org/en-US/docs/Web/HTTP/Connection_management_in_HTTP_1.x) 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](https://en.wikipedia.org/wiki/Head-of-line_blocking), 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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1713890723360/6b8737ae-d782-4cec-87f0-5f404565f899.png align="center")

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).

```http
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:

```diff
    +-----------------------------------------------+
    |                 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:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1713994903485/c47257ec-dd77-4287-9318-0a0e02f18e08.jpeg align="center")

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1713995085864/d0795c79-5d15-4b8a-9add-54ecab0f9d79.jpeg align="center")

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
