Http2 Service call pit – NGINX community


Understand HTTP2

As time goes on, more and more people are using HTTP. The drawbacks of HTTP1.1 are slowly becoming apparent.

1) Browser mode Some websites frequently send requests, resulting in a dominant website can not be used. Or all sites send requests frequently causing poor user experience and so on. Limit the number of concurrent requests per URL.

2) Improve the response speed of requests. Only one connection, only one TCP three-way handshake or TLS seven-way handshake. Http2.0 can handle three or four requests for the time it takes to process an HTTP1.1 request.

3) Improve the performance of the server and customer side (especially large Internet companies with heavy traffic, if using HTTP2.0, can reduce the HTTP server by half).

The HTTP client does not know whether the HTTP server supports HTTP2.0. In turn, the HTTP server does not know whether the HTTP client supports HTTP2.0. Why does this happen? It is impossible for all HTTP servers and HTTP clients to go directly from HTTP1.1 to HTTP2.0. Even in larger companies it is not practical to go directly from HTTP1.1 to HTTP2.0, so one troublesome thing is that there is an HTTP1 customer service, as well as an HTTP2 customer service. There is an HTTP2 server and there is an HTTP1 server. This two-dimensional, four-case coexistence.

One might ask, is it bad to only support HTTP1.1? Http2.0 has been used by clients with support for http2,.0.

So the designers of HTTP2.0 tried to solve this kind of trouble. A solution was introduced: negotiation.

The negotiation between https1.1 and Https2.0 is based on the ALPN mechanism. ALPNS is implemented based on TLS. When establishing a TLS link, the client will add its own protocol to the TLS protocol, and the server will select the most appropriate one from the protocol supported by the client. The selected protocol is then notified to the customer service. If the client does not send a supported HTTP protocol, the server uses HTTP1.1 by default.

HTTP does not have TLS, so it cannot transfer protocols based on TLS. The protocol maker uses the Upgrade mechanism. The client sends an empty request containing the Upgrade,Connection, and HTTP2-Settings headers. The server retrieves the supported protocol from Upgrade and responds to the request, including Upgrade and Connection in the request header. Then the negotiation will be successful.

Http1.1 and HTTP2.0 negotiation flow:

GET/HTTP/1.1 Host: Example Domain Connection: Upgrade, http2-settings Upgrade: h2c http2-settings: <base64url encoding of HTTP/2 SETTINGS payload>Copy the code

If the server does not support HTTP/2, it ignores the Upgrade field and returns an HTTP/1.1 response, for example:

HTTP/1.1 200 OK Content-Length: 243 Content-Type: text/ HTMLCopy the code

If the server supports HTTP/2, it can respond with the 101 status code and the corresponding header:

HTTP/1.1 100 Switching Protocols Connection: Upgrade Upgrade: H2CCopy the code

Summary:

1) HTTPS 1.1 and HTTPS.2.0 negotiation and http1.1 and HTTP2.0 negotiation are two sets of design schemes. HTTPS 1.1 and HTTPS.2.0 TLS are implemented automatically. The http1.1 / HTTP2.0 negotiation needs to be self-implemented.

2) The current trend, both the customer side and the server side need to support http1.1, HTTP2.0, https1.1, https2.0, technical implementation is more complex.


Two. The beginning of the problem

2.1.

The problem of this project is that a PROTOCOL_ERROR error is returned when the H2 service provided by Huawei is invoked through the JAVA terminal. However, the same writing method can be used to call the H2 service written by yourself. Baidu, Taobao and small can be called. That is to say, the program is working, but why huawei just return an error? The following is the reply from Huawei:

This means that the protocol used by the client is not correct, and the server cannot resolve it, requiring us to add coordination parameters in the packet header. The client modifies as required, but the problem persists; It is found that the server does not support the negotiation method to call, as follows:

2.2. Validation by other tools:

  1. The browser call was unsuccessful.

  2. The POSTMAN call was unsuccessful.

  3. The CURL call failed.

2.3. Jdk version supports H2

Java support for HTTP2 _ Growing Footprint -CSDN blog

  1. Java 8

TLS 1.2 is initially supported and is used by clients by default.

But to support HTTP2, Jetty’s ALPN module, ALPN-boot, is needed.

Java -xbootCLASSPath /p:< path_to_alpn_boot_JAR >…

  1. Java 9

TLS 1.2 is initially supported and is used by clients by default.

With JEP 244, TLS ALPN Extension supports ALPN and fully supports HTTP2.

  1. Java 10

With Java.

  1. Java 11

Same as Java 9, and further supports TLS 1.3.


Three. Investigation process

At this point, according to Part 2, neither of the following JAVA side calls to HTTP2 will work:

  1. In order to improve the efficiency of 5G core network, and are all for internal use, the specification does not provide the way of encryption call, so it cannot go through.

  2. If the http1.1 negotiation mode is used, the server must automatically select it according to the coordination parameters. But it’s not supported now either.

3.1. In the jars

Various methods have been repeatedly tried in this process:

1) Upgrade to JDk11 via native httpClient

HttpClient client = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_2) .priority(0) The sslContext (sslContext getInstance (" TLSv1.2 ")). The build ();Copy the code

2) Using okHttpClient3.2, the problem remains:

3) Using netty to call, the problem remains.

4) Coordinate the network experts on the client side to help analyze, through curl –http2 call, the problem is still the same.

3.2. Analyze successful cases of C++

Background C++ development client can be called normally, through understanding, C++ specified the mandatory use of H2 protocol to call, the package is captured and compared, found that when the client sends requests, there are indeed differences:

Problem location:

Does the Java side have parameters of the same type, which can be specified to force calls in H2 mode?

3.3. Try the curl command

First, try again and again with curl:

Curl failed when only the –http2 parameter is set.

The curl. Haxx. Se/docs/http2…. Http2-prior-knowledge http2-prior-knowledge

Curl enforces the H2 protocol to be invoked using –http2-prior-knowledge.

3.4. Search for class prior-knowledge parameters to solve the problem

In www.jianshu.com/p/9530d5825… To find a solution:

Try and verify:

Step 1: Upgrade the okHttpClient package to 4.1.0:

The second step, write the test program:

Step 3: Packet capture verification, successful:


4. Summary: Java calls H2 methods

4.1. Encrypted call

The negotiation between https1.1 and Https2.0 is based on the ALPN mechanism. ALPNS is implemented based on TLS. When establishing a TLS link, the client will add its own protocol to the TLS protocol, and the server will select the most appropriate one from the protocol supported by the client. The selected protocol is then notified to the customer service. If the client does not send a supported HTTP protocol, the server uses HTTP1.1 by default

4.2. Negotiation invocation

Github. IO /http2-spec/…

4.3. Enforce H2 invocation


More resources

Want more timely and comprehensive access to nginx-related technical dry goods, interactive q&A, course series, and event resources? Head to the NGINX open Source community:

– Official website: nginx.org.cn

– WeChat public: mp.weixin.qq.com/s/XVE5yvDbm…

– WeChat group: www.nginx.org.cn/static/pc/i…

– B station: space.bilibili.com/628384319