1. 程式人生 > >HTTP2.0學習 與 Nginx和Tomcat配置HTTP2.0

HTTP2.0學習 與 Nginx和Tomcat配置HTTP2.0

目錄

  • 一、HTTP2.0
    • 1.1 簡介
    • 1.2 新的特性
    • 1.3 h2c 的支援度
  • 二、Nginx 對 http2.0 的支援
    • 2.1 Nginx 作為服務端使用http2.0
    • 2.2 Nginx 作為客戶端使用 http2.0
  • 三、Tomcat 對 HTTP2.0 的支援
    • 3.1 、Tomcat 8.5
  • 四、擴充套件
    • 4.1、測試 h2c
    • 4.2、檢視瀏覽器是否支援 http2.0
    • 4.3、檢視網站是否支援 http2.0
    • 4.4、JAVA8 如何支援 HTTP2.0 TLS

一、HTTP2.0

1.1 簡介

HTTP/2(超文字傳輸協議第2版,最初命名為HTTP 2.0),簡稱為h2(基於TLS/1.2或以上版本的加密連線)或 h2c(非加密連線),是HTTP協議的的第二個主要版本。

1.2 新的特性

具體可以看這篇文章: https://segmentfault.com/a/1190000013420784

  1. 頭資料壓縮 Data compression of HTTP headers

  2. 伺服器推送 HTTP/2 Server Push

  3. 管線化請求 Pipelining of requests.

  4. 對資料傳輸採用多路複用,讓多個請求合併在同一 TCP 連線內 Multiplexing multiple requests over a single TCP connection, 因為每一個tcp 連線在建立的時候都需要耗費資源,而且在建立初期,傳輸也是比較慢的。
  5. 採用了二進位制而非明文來打包、傳輸 客戶端<——>伺服器 間的資料。

1.3 h2c 的支援度

HTTP/2 的設計本身允許非加密的 HTTP 協議,也允許使用 TLS 1.2 或更新版本協議進行加密。協議本身未要求必須使用加密,惟多數客戶端 (例如 Firefox, Chrome, Safari, Opera, IE, Edge) 的開發者宣告,他們只會實現通過TLS加密的HTTP/2協議,這使得經 TLS加密的HTTP/2(即h2)成為了事實上的強制標準,而 h2c事實上被主流瀏覽器廢棄。

二、Nginx 對 http2.0 的支援

2.1 Nginx 作為服務端使用http2.0

使用 http2.0 的條件

  1. Nginx 版本大於或等於 1.9.5 。
  2. openssl 版本 等於或者大於OpenSSL 1.0.2
  3. 編譯的時候開啟--with-http_v2_module

我們這裡配置的 h2 ,因為 瀏覽器對 h2c 基本不支援。

Nginx 在 1.9.5 才開始引入 http2.0 ,官方日誌。

編譯的時候加入 --with-http_v2_module,然後在 Nginx 配置中加上 http2

示例

listen 443 ssl http2 default_server;

2.2 Nginx 作為客戶端使用 http2.0

Nginx 作為服務端是可以進行配置 http2.0 的, 但是 Nginx 如果作為客戶端的話。Nginx 官方說的是不支援

Q: Will you support HTTP/2 on the upstream side as well, or only support HTTP/2 on the client side?

A: At the moment, we only support HTTP/2 on the client side. You can’t configure HTTP/2 with proxy_pass. [Editor – In the original version of this post, this sentence was incorrectly transcribed as “You can configure HTTP/2 with proxy_pass.” We apologize for any confusion this may have caused.]

But what is the point of HTTP/2 on the backend side? Because as you can see from the benchmarks, there’s not much benefit in HTTP/2 for low‑latency networks such as upstream connections.

Also, in NGINX you have the keepalive module, and you can configure a keepalive cache. The main performance benefit of HTTP/2 is to eliminate additional handshakes, but if you do that already with a keepalive cache, you don’t need HTTP/2 on the upstream side.

不能使用 proxy_pass配置 http2.0,  http2.0效能的主要優勢是減少多次tcp連線,我們通過配置keepalive  也可以做到這點。  (Google翻譯總結)

後續可以瞭解下 grpc .

grpc_pass grpc://localhost:50051

三、Tomcat 對 HTTP2.0 的支援

看了下 8.0 版本, 是不支援 HTTP2.0

看了下 8.5版本, 是支援 HTTP2.0

3.1 、Tomcat 8.5

怕上面文件沒有看清,下面文中的 h2 指的是(基於TLS/1.2或以上版本的加密連線),h2c 是非加密的

非加密的,用瀏覽器是訪問不了的(因為現在瀏覽器現在不支援),只支援 h2 。

官方文件寫到

Tomcat 是支援 h2h2c 的。 (你服務端支援沒有用啊,客戶端不支援,這不就gg了)

HTTP/2 is support is provided for TLS (h2), non-TLS via HTTP upgrade (h2c) and direct HTTP/2 (h2c) connections. To enable HTTP/2 support for an HTTP connector the following UpgradeProtocol element must be nested within the Connector with a className attribute of org.apache.coyote.http2.Http2Protocol.

<Connector ... >
  <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
</Connector>
Because Java 8's TLS implementation does not support ALPN (which is required for HTTP/2 over TLS), you must be using an OpenSSL based TLS implementation to enable HTTP/2 support. See the sslImplementationName attribute of the Connector.

Additional configuration attributes are available. See the HTTP/2 Upgrade Protocol documentation for details.

3.1.1、依賴環境

需要安裝 openssl 版本大於或者等於1.0.2

yum install  openssl 

3.1.2、h2c 配置(非加密)

也就加 <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />

示例配置

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150">
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
</Connector>

日誌中可以看到

The ["http-nio-8080"] connector has been configured to support HTTP upgrade to [h2c]

也就意味著 h2c 配置好了。

我們進行測試,使用的是curl, 但是這個 需要最新的版本,具體可以看擴充套件內容。

# curl --http2  http://192.168.174.128:8080
# tomcat 日誌 
192.168.174.128 - - [26/Mar/2020:09:54:28 +0800] "GET / HTTP/1.1" 101 -  
192.168.174.128 - - [26/Mar/2020:09:54:28 +0800] "GET / HTTP/2.0" 200 11195
# 101 是轉換協議,也就是 轉為協議為 http2.0 . 第二條日誌也就證實了。

3.1.3、h2 配置(加密)

也就意味著要進行配置證書了,

這個是8.5.53 版本的預設配置

    <!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
         This connector uses the APR/native implementation which always uses
         OpenSSL for TLS.
         Either JSSE or OpenSSL style configuration may be used. OpenSSL style
         configuration is used below.
    -->
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
               maxThreads="150" SSLEnabled="true" >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
        <SSLHostConfig>
            <Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
                         certificateFile="conf/localhost-rsa-cert.pem"
                         certificateChainFile="conf/localhost-rsa-chain.pem"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>

示例配置

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true" >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
       <SSLHostConfig>
            <Certificate certificateKeyFile="conf/server.key"
                         certificateFile="conf/ca.crt"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>

配置成功日誌

The ["https-openssl-nio-8443"] connector has been configured to support negotiation to [h2] via ALPN

訪問

 curl  --http2 -k   https://192.168.174.128:8443
 # 檢視 tomcat 的 localhost_access_log 日誌
 192.168.174.128 - - [26/Mar/2020:10:36:03 +0800] "GET / HTTP/2.0" 200 11195

發現 OK。

瀏覽器進行訪問,也是ok。

四、擴充套件

4.1、測試 h2c

需要安裝 curl ,curl 新版本的才支援,老版本不支援 http2.0.

rpm -ivh http://mirror.city-fan.org/ftp/contrib/yum-repo/city-fan.org-release-2-1.rhel7.noarch.rpm
yum clean all
yum makecache
yum update curl   --enablerepo=city-fan.org
# 可以看到 http2.0 就意味著支援了。
curl  -V
curl 7.69.1 (x86_64-redhat-linux-gnu) libcurl/7.69.1 NSS/3.44 zlib/1.2.7 libpsl/0.7.0 (+libicu/50.1.2) libssh2/1.9.0 nghttp2/1.31.1
Release-Date: 2020-03-11
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS GSS-API HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz Metalink NTLM NTLM_WB PSL SPNEGO SSL UnixSockets

參考文章: https://www.cnblogs.com/brookin/p/10713166.html

4.2、檢視瀏覽器是否支援 http2.0

檢視我們的瀏覽器是否支援 http2.0, 開啟網址進行測試。

4.3、檢視網站是否支援 http2.0

網址, 需要越牆。

4.4、JAVA8 如何支援 HTTP2.0 TLS

問題

  1. java8 的 TLS 不支援 ALPN(http2.0 TLS 需要ALPN)

    # http://tomcat.apache.org/tomcat-8.5-doc/config/http.html#HTTP/2_Support
    Because Java 8's TLS implementation does not support ALPN (which is required for HTTP/2 over TLS), you must be using an OpenSSL based TLS implementation to enable HTTP/2 support. See the sslImplementationName attribute of the Connector.
    
    java8 的 TLS 不支援 ALPN(http2.0 TLS 需要ALPN),我們必須基於 OpenSSL的TLS實現來啟用HTTP/2支援。
  2. 預設使用 org.apache.tomcat.util.net.jsse.JSSEImplementation,但在 Java8 情況下不支援 ALPN。

    # http://tomcat.apache.org/tomcat-8.5-doc/config/http.html#HTTP/2_Support
    When APR/native is enabled, the connectors will default to using OpenSSL through JSSE, which may be more optimized than the JSSE Java implementation depending on the processor being used, and can be complemented with many commercial accelerator components.
    
    The following NIO and NIO2 SSL configuration attributes are not specific to a virtual host and, therefore, must be configured on the connector.
    也就是說當  APR/native 開啟了, 聯結器會預設使用  OpenSSL

解決

方法一(沒行通)

我們需要關注這個引數:sslImplementationName

sslImplementationName   
The class name of the SSL implementation to use. If not specified and the tomcat-native library is not installed, the default of org.apache.tomcat.util.net.jsse.JSSEImplementation will be used which wraps JVM's default JSSE provider. Note that the JVM can be configured to use a different JSSE provider as the default. Tomcat also bundles a special SSL implementation for JSSE that is backed by OpenSSL. To enable it, the native library should be enabled as if intending to use the APR connector, and Tomcat will automatically enable it and the default value of this attribute becomes org.apache.tomcat.util.net.openssl.OpenSSLImplementation. In that case, the attributes from either JSSE and OpenSSL configuration styles can be used, as long as the two types are not mixed (for example, it is not allowed to define use of a Java keystore and specify a separate pem private key using the OpenSSL attribute).

當我們沒有安裝 tomcat-native ,將預設使用 org.apache.tomcat.util.net.jsse.JSSEImplementation,但是這個是不支援 ALPN,也就不支援 http2.0了。

看官方說到我可以配置 sslImplementationName="org.apache.tomcat.util.net.openssl.OpenSSLImplementation" ,但是我進行配置這個啟動就失敗了

    org.apache.catalina.LifecycleException: 初始化元件[Connector[HTTP/1.1-8443]]失敗。
        at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:440)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:139)
        at org.apache.catalina.core.StandardService.initInternal(StandardService.java:552)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:848)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:639)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:662)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:303)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:473)
    Caused by: java.lang.UnsatisfiedLinkError: org.apache.tomcat.jni.Pool.create(J)J
        at org.apache.tomcat.jni.Pool.create(Native Method)
方法二(可行)

安裝 tomcat-native,只要本地安裝了 tomcat-native ,就會預設使用 openssl. 雖然我們沒有開啟 ARP

yum install   openssl   tomcat-native  -y

Tomcat 開啟ARP 文章

因此我們建議,你在 java 8的 環境下需要使用 h2 的話,需要做到以下幾點

  1. 安裝 openssl 大於等於 1.0.2。
  2. 使用 Tomcat 8.5
  3. 安裝 tomcat-native。