A large percentage of web pages in browsers still use HTTP1.1 as their primary network communication protocol. But, uh, this stupid deal was made in 1999. It’s been xx years, and for years, the IETF in the US decided that this was no good. I have to come out to save the world, in Chrome’s advocacy, borrow Chrome SPDY as a predecessor to HTTP2, namely, HTTP2 is SPDY/3 draft optimization version.

So why did HTTP2 come along and solve something HTTP1.1 couldn’t?

In a nutshell

  • H2 is a binary protocol and H1 is a hypertext protocol. The content is not the same

  • H2 follows multiplexing, that is, replacing content under the same host and establishing a connection only once. H1 is not (idiot)

  • H2 can use HPACK for header compression,H1 will send any request

  • H2 allows the server to pre-push resources needed for a web page into the browser’s memory.

Next, let’s see what specific features H2 has

The features of HTTP2

First, why HTTP2 is a binary protocol.

HTTP2 binary

Speaking of H2 binaries, let’s start with H1’s hypertext protocol. HTTP1.1 will need to find the position of the beginning and end of each frame when sending a request, and when writing, also need to remove extra Spaces, and select the best way to write. And if it is HTTP+TLS, the performance loss is relatively well, because TLS itself handshake protocol, as well as the encryption way, to a certain extent, the content of text information will be processed and so on. All of these undoubtedly have a significant impact on HTTP1.1’s speed. So,HTTP2 doesn’t take this approach, and instead, goes straight to binary. So, how does H2 do binary transfer? Here, take a look at Grigorik’s POWERPOINT presentation at the Velocity conference.

Yes,H2 is a protocol built into the application layer that automatically separates the Header from the Body when receiving requests from the server.

HTTP2 multiplexing

In H1, there is a head-of-line blocking when multiple requests are sent. In this way, resources can only be loaded one by one in order. The following symptoms may occur:

The previous resource has too much content and is loaded at one time. Even if there are more important resources behind, they also need to wait. In H2, however, there are no such restrictions. He will directly divide the different resources into tiny binary frames for transmission.

Of course, you don’t have to worry about transmitting errors every time, because the format inside each frame is actually:

Each frame that is transmitted has the following attributes: Length, Type, Flags, Stream Identifier, and frame payload.

only one Tcp connection

This feature is based on the mechanism of multiplexed of binary transmissions. In a nutshell:

  • A domain requires only one TCP connection

Because in H1, although there is a Connection:keep-alive feature, you can make your TCP disconnect a little later. This doesn’t work because the H1 has a built-in max-connections number. To speed up more resources, you have to open a few more domains to connect to, which is both expensive and too expensive to maintain. This is known as Domain Sharding. However, in H2, it all becomes special SB… Think,H2 itself can be realized, a TCP, unlimited resource characteristics. The most obvious feature: Akamai HTTP2 demo.

The number of resources requested by HTTP2 is up to eight. The number of resources requested by HTTP2 is up to eight. At most (not at most) only one… That’s enough of the stupid nature of HTTP1.1… So how does he actually make multiple requests for resources in one TCP session? Multiplexed video with reference to NewCircle Training. We used to send HTTP1.1:

In HTTP2, we change the way we request:

Some students may ask: he put multiple content in a stream for transmission, how to ensure the order of resources? That’s a good question! The HTTP2 feature is indeed built on stream. As mentioned above,HTTP2 divides resources into minimal frames for transmission to achieve interleave and priority effects. The inside of each frame is as shown below:

To ensure that the order and priority features of HTTP2 are maintained, some additional information is required:

  • a unique stream ID

  • different priority

Of course, in addition to these basic optimizations,HTTP2’s HEADER optimizations are also costly.

HEADER Compression

HEADER optimization, again, is due to HTTP1.1’s HEADER mechanism, which requires a lot of HEADER content, even cookies, on every request. So,SPDY thought this was not good, and then used the GZIP compression method, but this is very easy to crack and hijacking, resulting in security issues. HTTP2 learned from this lesson and decided to develop a set of optimization solutions, that is, since the replacement of headers is not very frequent, I will do a Server side cache, in your connection to the valid time, the client will use the repeated headers. This is the HPACK compression of HTTP2. HPACK compression goes through two steps:

  • The transmitted value will go through Huffman coding. to save resources.

  • For server and client synchronization, both sides need to keep a Header list, and each time a request is sent, it is checked for updates

Ok, so there’s a problem with that. The first request is definitely the slowest. Because all of his lists need to be initialized. But there’s really no way… If you send it by guessing the Header, you might end up with an error. In fact, each list is also divided into static list and dynamic list. The difference between the two is as follows:

  • Static: Stores common headers, such as method and path

  • Dynamic: stores user-defined protocol headers. For example,custom- name and custom-method

The whole process can be expressed as follows:

As you can see, the req/ RES headers are all in the same table. This may be a bit of a memory drain, but it’s still pretty fast.

Here, there are a few additional points to mention:

  • All header protocols are unchanged in HTTP2, cache still cache-Control, eTag,last-modifier

  • The response headers are all lowercase. Such as server status.

  • Request headers are all lowercase, with a few exceptions: :method, :scheme, :authority, and :path The basic headers are required: pseudo-header fields.

HTTP2 priority

As mentioned earlier, each frame of HTTP2 carries some relevant information, such as the weight –priority. There is also dependency. That is, if a client wants to request the index.html resource, the server will return both index.js and index.css. Reduce client to send more requests, equivalent to a Server Push technology, and the current SSE is very similar. To implement this feature, there are two basic criteria:

  • Each stream needs a number from 1 to 256 to represent its weight

  • Each stream should clearly indicate what its dependencies are

An actual graph looks like this:

Let’s use the picture above as an illustration. If a C resource depends on a D resource, then D is the parent of C. And then continue in that order. If there are two nodes under one root node, say the first A,B. How do you divide it up? In this case, use the number above the main A and B mentioned above. A-12, B-4. Divide network resources — essentially bandwidth and CPU — into A cake, so that at this point,A gets 3/4 of the resources and B gets 1/4. In HTTP2, fractions are not fractions. This does not matter because HTTP2 transmits binary data, so incomplete resources are guaranteed. It’s just that those files move faster. Let’s follow the third diagram to explain:

  1. First, D takes up 100% of the resources to send

  2. After D sends the data, C uses 100% of the resources to send the data

  3. In this case, since A is 3/4 and B is only 1/4, the resources are allocated according to the weight, and then continue to send the file to the end

HTTP2 Server PUSH

This mechanism is the second major HTTP2 feature, namely, the one-to-many mechanism to request resources. Because considering that before, the front-end request resource is through the resolution of document to achieve the fetch of resources. It’s kind of stupid… You know, I know this resource needs to be loaded, but I can’t send it to you in a request. I need to wait until you ask for it. This creates a communication problem. So, HTTP2 decided to solve this bug by developing a mechanism for implementing Server Push resources.

Here, we requested page.html, but actually gave us script.js and style.css automatically by pushing promise.server. This saves the cost of the two requests. This approach is also known as inlining CSS and inlining script. However, using HTTP2 as a mechanism has several advantages over Inlining:

  • Push resources can be cached in the browser

  • Different web pages can use the cache without being relaunched

  • The push resource is transmitted over multiplexed

  • Push resources can be identified with priority

  • The client has the right to cancel the loading of the push resource

  • Resources for push must be codomain

HTTP2 feature (HTTP2 feature) HTTP2 feature (HTTP2 feature) However, once you dig deeper, you will find that the real work is done when the theory is relatively sound. All are some engineering content, just write it down. What about the specific requests involved? In simple terms, when HTTP1.1 makes a request, as shown below:

Add HTTP2.0 server push to create:

It puts the associated resource in the cache and fetches it directly from the cache the next time a request is made for the specified resource.

So, here, let’s take a closer look at the specific HTTP2 protocol -frame content

HTTP2 frame content

Here’s a picture:

This is the same as the picture above, only clearer. HTTP2 uses it for all communication, almost as much as the TCP frame content. HTTP2 by setting the length, type, Flags, R, Stream Identifier to identify a frame. All of this takes up 9B. Specifically:

  • Length is the size of the frame in 24-bit format. The size of the frame can be up to 2^24B (~16MB). However, in practice, the general on-line setting is 16KB. Of course, you can do this manually. However, this does not reflect the characteristics of small files, streaming

  • The 8-bit type field indicates the type of the frame

  • The 8-bit Flags field indicates what type the frame contains

  • 1-bit R is a reserved field, always set to 0

  • A 31-bit identifier to indicate the stream’s unique ID. Very useful. This flag is the one used to ensure orderliness.

Do you know why I put Length at the beginning? It’s just to make the parser parse faster, because when the Parser starts parsing, first of all, I know what frame you’re going to pass, and I know what type you’re going to pass, and then I just assign the frame to a specific engine for parsing. And then I’m just going to skip and go to a frame and continue parsing. Then, the final data acceptance is completed.

Since different types can be parsed by different engines, how many types are there? Don’t bother counting… Let’s get straight to it.

  • DATA: corresponds to the message Body content. That is, the content of the response body returned

  • HEADERS: this is the corresponding HEADERS.

  • PRIORITY: Identifies the PRIORITY of the frame as mentioned earlier.

  • RST_STREAM: signal to terminate the resource

  • PUSH_PROMISE: This is important. This server PUSH above has a lot to do with it. This is used to set the flag of related resources sent by the server itself.

  • SETTINGS: Used to configure the connection between the client and server

  • GOAWAY: tells the server to stop sending related resources

  • CONTINUATION: As opposed to GOWAY, continues to send related resources

  • WINDOW_UPDATE: Use flow control for flow control.

HTTP2 transfer process

HTTP2 is also built on a TCP connection, and it also needs to send a request and get a response. So what was his first message? Is it a resource request? HTML? JS? CSS? Actually, No~HTTP2 Sends HEADERS in the first request, because a Virtually list needs to be created at both ends to store the HEADERS for HPACK compression. The diagram below:

Check its Type carefully and you can find that it is a HEADERS. Store two different header tables — static table && Dynamic table.

To prevent stream ids from duplicating, the client and server specify: The client-initiated stream can be an odd stream-ID, and the server-initiated stream can be an even stream ID.

HTTP2 practice process

The first agreement to appear must be the communication between >=2. That is the communication protocol between server and Browser for HTTP2. So, to be successful, HTTP2 must be supported not only by the server but also by your browser. So far, so good

On the Server side, support for HTTP2 is simple:

  • Nginx version > 1.10

  • Openssl >1.0.2h

  • Have your own CA certificate.

So, we start from CA certificate, here, the first amway about the major cloud platform, as long as you bought a server in his that automatically back to you to provide free and formal CA certificate, my certificate is sent in Tencent cloud. Change it once a year. Here, I press TX(Tencent) on. When your application is successful, he will give you a ZIP file. When unzipped, you get two files:

  • Certificate file: 1_www.domain.com_cert.crt

  • Private key file: 2_www.domain.com.key

These two files are going to be useful later. For nginx and OpenSSL. Generally, the server version is relatively low, so here we take the way of manual compilation.

1.1.0 openssl wget -o openssl.tar.gz -c HTTP: / / https://www.openssl.org/source/openssl-1.1.0.tar.gz / / extract tar ZXF openssl. Tar. Gz / / renamed openssl - 1.1.0 openssl/mv/download Nginx 1.11.4 wget source - c https://nginx.org/download/nginx-1.11.4.tar.gz tar ZXF nginx - 1.11.4. Tar. Gz CD nginx 1.11.4 / / / /configure --prefix=/usr/local/nginx \ --conf-path=/etc/nginx/nginx.conf \ --with-openssl=.. /openssl \ --with-http_v2_module \ --with-http_ssl_module \ --with-http_gzip_static_module // make && sudo make installCopy the code

So here, I’m going to go straight to gist. You can download it directly and run it using.. /http2.sh.

Setting environment Variables

/usr/local/nginx/sbin /usr/local/nginx/sbin Connect nginx to /usr/sbin.

ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginxCopy the code

We are now ready to use the nginx command globally.

Configure nginx conf

/etc/nginx/nginx.conf Paste paste to paste the code:

# user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_comp_level 5; gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php; include /etc/nginx/sites-available/*.conf; }Copy the code

Not to mention above, the main content is still in the server. I’m using nginx + nodeJS here. So there’s a layer of proxy behind it.

server { listen 80; # redirect previous HTTP protocol server_name villainhr.com www.villainhr.com; return 301 https://www.villainhr.com$request_uri; } server { listen 443 ssl http2; server_name www.villainhr.com; root /var/www/myblog/app; ssl on; Ssl_certificate /etc/nginx/private/1 _www.villainhr.com_cert. CRT; ssl_certificate_key /etc/nginx/private/2 _www.villainhr.com.key; Ssl_session_timeout 5m; Ssl_protocols TLSv1 TLSv1.1 TLSv1.2; Ssl_ciphers ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:! MD5; ssl_prefer_server_ciphers on; add_header Strict-Transport-Security max-age=15768000; ssl_stapling on; ssl_stapling_verify on; location / { proxy_pass http://localhost:8000; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~.(js|css|gif|jpg|jpeg|ico|png|bmp|swf|GIF|JPG|JPEG|ICO|PNG|BMP|SWF) $ { root / root /var/www/myblog/app/public; expires 2d; add_header Cache-Control "no-cache"; add_header Pragma no-cache; log_not_found off; }}Copy the code

Then, run it directly using nginx. If all goes well, your HTTP2 Server is done. If there’s a configuration error or something. If you don’t trust, go directly to Mozilla to install one.