In-depth understanding of the Web protocol (3): HTTP 2

This article will introduce all aspects of the http2 protocol in detail. The knowledge points are as follows:

  • HTTP 2 connection establishment

  • The relationship between frames and streams in HTTP 2

  • The mystery of traffic saving in HTTP 2: HPACK algorithm

  • The ability of Server Push in HTTP 2 protocol

  • Why does HTTP 2 implement flow control?

  • Problems encountered by the HTTP 2 protocol

1. The establishment of HTTP 2 connection

Unlike many people's inherent impressions, the HTTP 2 protocol itself does not stipulate that it must be established on top of TLS/SSL, and it can also complete the establishment of HTTP 2 connections using ordinary TCP connections. It's just that for security, all browsers on the market only support the HTTP 2 protocol based on TLS/SSL by default. Simply put, we can call the HTTP 2 protocol built on top of the TCP connection H2C, and the one built on top of the TLS/SSL protocol can be understood as H2.

input the command:

tcpdump -i eth0 port 80 and host nghttp2.org -w h2c.pcap &

Then use curl to access the HTTP 2 site based on the TCP connection, which is port 80 (there is no way to access the browser here, because the browser does not allow it)

curl http://nghttp2.org --http2 -v

In fact, looking at the log can also roughly understand the process of establishing this connection:

In-depth understanding of the Web protocol (3): HTTP 2

We copy the pcap file from TCPDump to the local, then open it with Wireshark and restore the entire HTTP 2 connection establishment message:

The first is the upgrade of HTTP 1.1 to HTTP 2 protocol

In-depth understanding of the Web protocol (3): HTTP 2

Then the client also needs to send a "magic frame":

In-depth understanding of the Web protocol (3): HTTP 2

Finally, a setting frame needs to be sent:

In-depth understanding of the Web protocol (3): HTTP 2

After that, let’s take a look at how the TLS-based HTTP 2 connection is established. Considering encryption and other factors, we need to do some preparations in advance. You can download this plugin in Chrome.

In-depth understanding of the Web protocol (3): HTTP 2

Then open any webpage as long as you see the lightning icon in blue, it means that the site supports HTTP 2; otherwise, it does not. As shown below:

In-depth understanding of the Web protocol (3): HTTP 2

To output information such as TLS/SSL of the Chrome browser to a log file, additional system variables need to be configured, as shown in the figure:

In-depth understanding of the Web protocol (3): HTTP 2

Then configure the SSL-related settings in our Wireshark.

In-depth understanding of the Web protocol (3): HTTP 2

In this way, when the browser interacts with the TLS protocol, the relevant encryption and decryption information will be written into this log file, and our Wireshark will use the information in this log file to decrypt our TLS messages.

With the above foundation, we can proceed to analyze the HTTP 2 protocol based on TLS connection. For example, we visit tmall's sitehttps://www.tmall.com/  and open our Wireshark.

In-depth understanding of the Web protocol (3): HTTP 2

Looking at the marked place, it can be seen that after the TLS connection is established and then continue to send the magic frame and setting frame, it means that the HTTP 2 connection is really established. Let's look at the client hello message of the TLS message:

In-depth understanding of the Web protocol (3): HTTP 2

The information of this alpn protocol represents which two protocols the client can accept. The server hello message clearly tells us to use the H2 protocol.

In-depth understanding of the Web protocol (3): HTTP 2

This is also one of the most important advantages of HTTP 2 compared to the spdy protocol: the spdy protocol strongly relies on TLS/SSL, and the server has no choice. The HTTP 2 protocol will carry the alpn extension when the client initiates a request, which means that when the client sends a request, it will tell the server which protocols I support. This allows the server to choose whether I need to use TLS/SSL.

Second, the relationship between frames and streams in HTTP 2

In-depth understanding of the Web protocol (3): HTTP 2

Simply put, HTTP 2 simulates the concept of "streaming" in the transport layer TCP at the application layer, thus solving the problem of congestion at the head of the line in the HTTP 1.x protocol. In the 1.x protocol, the HTTP protocol is Composed of messages one by one, on the same TCP connection, the response to the previous message is not returned, and subsequent messages cannot be sent. In HTTP 2, this restriction is removed and the so-called "message" is defined as a "stream". The order between the stream and the stream can be disordered, but the order of the frames in the stream cannot be disordered. As shown:

In-depth understanding of the Web protocol (3): HTTP 2

That is to say, on the same TCP connection, multiple streams can exist at the same time. These streams are composed of frame frames. There is no order relationship between the stream and the stream, but the frames within each stream are in order. Note that the numbers such as 135 in this picture are actually stream id. Although there is a concept of frame in WebSocket, because there is no stream id in WebSocket, Websocket has no multiplexing function. HTTP 2 has the ability to multiplex because of the stream id. There can be n streams on a TCP connection, which means that the server can concurrently process n requests at the same time and then respond to these requests to the same TCP connection at the same time. Of course, the ability to transmit n streams on the same TCP connection is also limited. When the HTTP 2 connection is established, the setting frame will contain this setting information. For example, when visiting the Tmall site in the figure below, the setting frame message carried by the browser indicates that the browser, the HTTP 2 client, can support a maximum concurrent stream of 1000.

In-depth understanding of the Web protocol (3): HTTP 2

When the Skycat server returned the response of this setting frame, it informed the browser that the maximum concurrent stream I can support is 128.

In-depth understanding of the Web protocol (3): HTTP 2

At the same time, we also need to know that in the HTTP 2 protocol, the stream id being a singular number represents a stream initiated by the client, and an even number represents a stream initiated by the server (it can be understood as the server actively pushing).

3. The mystery of traffic saving in HTTP 2: HPACK algorithm

Compared with the HTTP 1.x protocol, the HTTP 2 protocol has also made great improvements in traffic consumption. It is mainly divided into three parts: static dictionary, dynamic dictionary, and Huffman code. You can install the following tools to detect the effect on traffic saving:

apt-get install nghttp2-client

Then you can detect some sites that have HTTP 2 enabled. Basically, the traffic saved is 25%, and if you visit frequently, it will be more:

In-depth understanding of the Web protocol (3): HTTP 2

For traffic consumption, in fact, the biggest improvement of HTTP 2 compared to HTTP 1.x protocol is that in HTTP 2 we can compress HTTP headers, while in the past HTTP 1.x protocol, gzip etc. could not The header is compressed, especially for the vast majority of requests. In fact, the proportion of header is the largest.

Let us first understand the static dictionary, as shown in the figure:

In-depth understanding of the Web protocol (3): HTTP 2

This is not difficult to understand. It is nothing more than expressing our commonly used HTTP headers with fixed numbers, which of course can save traffic. It should be noted here that some value headers are more complicated, their value There is no static dictionary. For example, the cache control field of cache-control, because there are too many values ​​behind it, it cannot be solved with a static dictionary, but only by Huffman coding. The following figure can show the traffic saving effect of the compression algorithm of HPACK:

In-depth understanding of the Web protocol (3): HTTP 2

For example, let’s look at the header 62. User-agent refers to the browser. Generally, this header information will not change when we request it. Therefore, it is finally optimized by the hpack algorithm and then only needs to be transmitted during subsequent transmissions. The number 62 can represent its meaning.

Another example is the following figure:

In-depth understanding of the Web protocol (3): HTTP 2

The same is true. When multiple requests are sent continuously, in most cases only the path is changed, and the rest of the header information is unchanged. Based on this scenario, only the header information of path is the final transmission.

Finally, let's take a look at the core of the hpack algorithm: Huffman coding. The core idea of ​​Huffman coding is to use shorter codes for higher frequency, and longer codes for lower frequency (the predecessor of HTTP 2 protocol uses dynamic Huffman coding, while HTTP 2 protocol uses The static Huffman coding is selected).

In-depth understanding of the Web protocol (3): HTTP 2

Let's look at a few examples:

In-depth understanding of the Web protocol (3): HTTP 2

For example, this header frame, pay attention to the header information of this method: get. Because the index value of method:get in the static index table is 2. For the value of this kind of key and value in the index table, we use one byte, which is 8 bits, to identify, the first bit is fixed at 1. , The remaining 7 bits are used to represent the value in the index table, where the value of the method:get index table is 2, so this value is 1000 0010, which is 0x82 when converted to hexadecimal.

In-depth understanding of the Web protocol (3): HTTP 2

Let's look at a group of header examples where the key is in the index table and the value is not in the index table.

In-depth understanding of the Web protocol (3): HTTP 2

For the case where the key is in the index table and the value is not in the index table, it is always the byte at the beginning of 01, and the next 6 bits (111010 converted to decimal is 58) are the value of the static index, and the value of index in the index of the user-agent It is 58 plus the 2 bits at the beginning of 01, which is converted into binary is 01111010, and hexadecimal is 7a. Then look at the second byte, 0xd4, 0xd4 converted to binary is 1 101 0100, where the first bit represents the Huffman encoding used, and the key-value value of the following 7 bits requires several words In terms of section, here is 101 0100, which is converted into decimal number 84, which means that the value behind this user-agent needs 84 bytes to represent. Let’s count the number of bytes in the figure 16*5+first The 4 bytes behind row d4 are equal to 84 bytes.

Finally, let's look at an example where the key and value are not in the index table.

In-depth understanding of the Web protocol (3): HTTP 2

Fourth, the ability of Server Push in HTTP 2 protocol

As we mentioned earlier, the biggest improvement of H2 over H1.x protocol is that H2 can transmit n streams simultaneously on the basis of a single TCP connection. So as to avoid the problem of congestion at the head of the H1.x protocol. In fact, in most front-end pages, we can also use the Server Push capability of the H2 protocol to further improve the page loading speed. For example, usually when we use a browser to visit an Html page, only when the html page is returned to the browser and the browser kernel parses that there are resources such as CSS or JS in the Html page, the browser will send the corresponding CSS or JS Request, when CSS and JS come back, the browser will render further. Such a process will usually cause the browser to be in a white screen for a period of time, thereby reducing the user experience. With the H2 protocol, when the browser accesses an Html page to the server, the server can actively push the corresponding CSS and JS content to the browser, so that the step of resending CSS and JS requests after the browser can be omitted.

Some people have a certain degree of misunderstanding about Server Push, believing that this technology allows the server to send "notifications" to the browser, and even compare it with WebSocket. This is not the case. Server Push just saves the browser from sending requests. Only when "If you don't push this resource, the browser will request this resource", the browser will use the pushed content. Otherwise, if the browser itself does not request a resource, pushing this resource will only consume bandwidth in vain. Of course, if the client is communicating with the server instead of the browser, then the HTTP 2 protocol can naturally complete the push function. Therefore, when the HTTP 2 protocol is used, there is still a certain difference in function between the client or the browser communicating with the server.

In-depth understanding of the Web protocol (3): HTTP 2

To demonstrate this process, let's write a piece of code. Considering that the browser must establish a TLS connection to access the HTTP 2 site, we must first generate the corresponding certificate and secret key.

In-depth understanding of the Web protocol (3): HTTP 2

Then turn on HTTP 2, and actively push the CSS file referenced in Html when receiving the Html request.


package main

import (
    "fmt"
    "net/http"

    "github.com/labstack/echo"
)

func main() {

    e := echo.New()
    e.Static("/", "html")
    //主要用来验证是否成功开启http2环境
    e.GET("/request", func(c echo.Context) error {
        req := c.Request()
        format := `
          <code>
            Protocol: %s<br>
            Host: %s<br>
            Remote Address: %s<br>
            Method: %s<br>
            Path: %s<br>
          </code>
        `
        return c.HTML(http.StatusOK, fmt.Sprintf(format, req.Proto, req.Host, req.RemoteAddr, req.Method, req.URL.Path))
    })

    //在收到html请求的时候 同时主动push html中引用的css文件,不需要等待浏览器发起请求
    e.GET("/h2.html", func(c echo.Context) (err error) {
        pusher, ok := c.Response().Writer.(http.Pusher)
        if ok {
            if err = pusher.Push("/app.css", nil); err != nil {
                println("error push")
                return
            }

        }

        return c.File("html/h2.html")
    })
    // 
    e.StartTLS(":1323", "cert.pem", "key.pem")
}

Then when Chrome visits this page, look at the NetWork panel:

In-depth understanding of the Web protocol (3): HTTP 2

It can be seen that this CSS file is our initiative to push over. Look at Wireshark again.

In-depth understanding of the Web protocol (3): HTTP 2

It can be seen that the stream id of 13 is a request initiated by the client, because the id is singular. In this stream, there is a push_promise frame. This frame is sent by the server to the browser. Take a look at its specific content.

In-depth understanding of the Web protocol (3): HTTP 2

It can be seen that this frame is used to tell the browser which resource I actively pushed to you, and the stream-id of this resource is 6. In the figure, we also see that a data with a stream-id of 6 is being transmitted. This is the CSS file actively pushed by the server. At this point, a complete Server Push interaction is complete.

However, the challenge of actually applying Server Push online is far more complicated than in our demo. The first is that most CDN vendors (unless self-built CDN) have limited support for Server Push. It is impossible for us to make every resource request directly hit our origin server. Most static resources are pre-installed in the CDN. Secondly, for static resources, we also need to consider the impact of caching. If it is a static resource request sent by the browser itself, the browser can determine whether I really need to request this resource based on the cache status, and Server Push It is initiated by the server. In most cases, the server does not know whether the cache of this resource has expired. Of course, after the browser receives the push Promise frame, it can query its own cache status and then initiate a RST_STREAM frame to inform the server that this resource is cached and does not need to be sent anymore, but you can’t guarantee that when this RST_STREAM reaches the server, the server The data frame that is actively pushed has not been sent yet. Therefore, there will still be some bandwidth waste. In general, Server Push is still a very effective means to improve the front-end user experience. After using Server Push, the browser’s performance index idle index can generally be increased by 3-5 times (after all, the browser does not need to wait for the Html to be parsed before requesting CSS and JS too).

5. Why does HTTP 2 implement flow control?

Many people do not understand why the TCP transport layer has implemented flow control, and our application layer HTTP 2 also needs to implement flow control. Let's look at a picture below.

In-depth understanding of the Web protocol (3): HTTP 2

In the HTTP 2 protocol, because we support multiplexing, which means that we can send multiple streams at the same time. In the same TCP connection, in the above figure, each color represents a stream. You can see that we have a total of There are 4 kinds of streams. Each stream has n frames. This is very dangerous. Assuming we use multiplexing in the application layer, n frames will be sent to the target server at the same time. When the traffic reaches its peak, it will trigger TCP congestion control, which will block all subsequent frames and cause the server to respond too slowly. This problem naturally does not exist in HTTP 1.x because multiplexing is not supported. And we mentioned many times before, a request from the client to the server has to go through many proxy servers. The memory size and network conditions of these proxy servers may be different, so do a flow control at the application layer to avoid triggers. TCP flow control is very necessary. The flow control strategy in the HTTP 2 protocol follows the following principles:

  1. Both the client and the server have flow control capabilities.

  2. The sender and receiver can independently set flow control capabilities.

  3. Only the data frame requires flow control, and no other header frames or push promise frames are required.

  4. The flow control capability is only for both ends of the TCP connection. Even if there is a proxy server in the middle, it will not be transparently transmitted to the source server.

Visit Zhihu's site to take a look at packet capture.

In-depth understanding of the Web protocol (3): HTTP 2

These identifying window_update frames are so-called flow control frames. Let's open one at random and take a look, and we can see the frame size that this flow control frame tells us.

In-depth understanding of the Web protocol (3): HTTP 2

As smart as you can imagine, since HTTP 2 can achieve flow control, it must also be used for priority. For example, in the HTTP 1.x protocol, we visit an Html page, which contains resources such as JS, CSS and images. We send these requests at the same time, but these requests have no concept of priority. Whoever goes out first comes back Both are unknown (because you don’t know if these CSS and JS requests are on the same TCP connection. Since they are scattered in different TCPs, it is uncertain which is faster and slower), but from the perspective of user experience In other words, CSS must have the highest priority, then JS, and finally images. This can greatly reduce the time of the browser's white screen. This capability is implemented in HTTP 2. For example, if we visit Sina's site and capture the package, we can see:

You can look at the priority of this CSS frame:

In-depth understanding of the Web protocol (3): HTTP 2

JS priority

In-depth understanding of the Web protocol (3): HTTP 2

Finally, the priority of the gif picture, it can be seen that this priority is the lowest.

In-depth understanding of the Web protocol (3): HTTP 2

With the weight keyword to identify the priority, the server knows which requests need to be responded to and which can be sent later. In this way, the overall experience that the browser provides to users will become better.

6. Problems encountered by HTTP 2 protocol

The HTTP 2 protocol based on TCP or TCP+TLS still encounters many problems, such as the problem of too long handshake time. If it is the HTTP 2 protocol based on TCP, then at least three handshake is required. If it is the HTTP 2 protocol of TCP+TLS, except The TCP handshake also has to go through TLS multiple handshake (TLS1.3 can already achieve only one handshake). Each handshake needs to send a message and then the ack that receives this message can perform the next handshake. In a weak network environment, it is conceivable that the efficiency of this connection establishment is extremely low. In addition, the congestion problem inherent in the TCP protocol has been plagued by the HTTP 21.x protocol and the HTTP 2 protocol. Let's take a look at the promotional image of Google Spdy to understand the nature of this congestion more accurately:

In-depth understanding of the Web protocol (3): HTTP 2

Figure 1 is very easy to understand, we send 3 streams at the same time under the support of multiplexing, and then send them to the server through TCP/IP protocol, and then TCP protocol transmits these data packets to our application layer. Note that there is a The condition is that the order of sending packets must be consistent with the order of receiving packets. In the figure above, you can see that the order of the squares is the same, but if you encounter the situation in the figure below, for example, if these data packets happen to be lost in the first red data packet, then even if the subsequent data packets have been In the server machine, the data cannot be passed to our application layer protocol immediately, because the TCP protocol stipulates that the order of receiving must be consistent with the order of sending. Since the red data packet is lost, the subsequent data packets are You can only block in the server and wait until the red data packets have successfully reached the server after resending, and then pass these data packets to the application layer protocol.

In addition to the above-mentioned shortcomings of the TCP protocol, another problem is that the implementer of the TCP protocol is at the operating system level. Any language, including Java, C, C++, Go, etc., is the ultimate implementer of the so-called Socket programming interface exposed to the outside world. In fact, it is the operating system itself. It is very, very difficult for the operating system to upgrade the implementation of the TCP protocol. Moreover, it is unrealistic for so many devices in the entire Internet to realize the upgrade of the TCP protocol as a whole (the IPV6 protocol upgrade is too slow for this reason. ). Based on the above problems, Google encapsulated a layer of quic protocol based on the udp protocol (in fact, many application layer protocols based on the udp protocol partially implement several functions of the TCP protocol on the application layer) to replace HTTP 21.x-HTTP The TCP protocol in 2.

We turn on the quic protocol switch in Chrome:

In-depth understanding of the Web protocol (3): HTTP 2

Then visit youtube (domestic station b actually supports it).

In-depth understanding of the Web protocol (3): HTTP 2

It can be seen that the quic protocol has been supported. Why this option is turned off by default in the Chrome browser is actually well understood. This quic protocol is actually made by Google itself, and has not been officially included in the HTTP 3 protocol. Everything is still in the draft. So this option is turned off by default. What are the main improvements of the quic protocol compared to the original TCP protocol? In fact, the original queue transmission message is changed to no queue transmission, so naturally there is no problem of congestion at the head of the queue.

In-depth understanding of the Web protocol (3): HTTP 2

In addition, HTTP 3 also provides the ability to change the port number or ip address to reuse the previous connection. Personal understanding of the features supported by this protocol may be more for IoT considerations. The IP of many devices in the Internet of Things may change all the time. The ability to reuse previous connections will greatly improve the efficiency of network transmission. In this way, it is possible to avoid the current disadvantage that it takes at least 1-3 rtt to continue data transmission after reconnecting to the network after disconnection.

In-depth understanding of the Web protocol (3): HTTP 2

Finally, in an extremely weak network environment, HTTP 2 may not perform as well as HTTP 1.x, because there is only one TCP connection under HTTP 2. Under a weak network, if the packet loss rate is extremely high, TCP will continue to be triggered. Timeout retransmissions at the level cause a backlog of TCP packets, and the delay in delivering packets to the application layer above, but in HTTP 1.x, because multiple TCP connections can be used, to a certain extent, the backlog of packets The situation will not be as serious as HTTP 2. This is the only place where I think the HTTP 2 protocol is inferior to HTTP 1.x. Of course, this pot is TCP, not HTTP 2 itself.

More reading:

Author: vivo Internet -WuYue

Guess you like

Origin blog.51cto.com/14291117/2634187