HTTP/2(超文本传输协议第2版,最初命名为HTTP 2.0),简称为h2(基于TLS/1.2或以上版本的加密链接)或 h2c(非加密链接),是HTTP协议的的第二个主要版本。html
具体能够看这篇文章: https://segmentfault.com/a/1190000013420784java
头数据压缩 Data compression of HTTP headerslinux
服务器推送 HTTP/2 Server Pushnginx
管线化请求 Pipelining of requests.shell
对数据传输采用多路复用,让多个请求合并在同一 TCP 链接内 Multiplexing multiple requests over a single TCP connection, 由于每个tcp 链接在建立的时候都须要耗费资源,并且在建立初期,传输也是比较慢的。apache
采用了二进制而非明文来打包、传输 客户端<——>服务器 间的数据。segmentfault
HTTP/2 的设计自己容许非加密的 HTTP 协议,也容许使用 TLS 1.2 或更新版本协议进行加密。协议自己未要求必须使用加密,唯多数客户端 (例如 Firefox, Chrome, Safari, Opera, IE, Edge) 的开发者声明,他们只会实现经过TLS加密的HTTP/2协议,这使得经 TLS加密的HTTP/2(即h2)成为了事实上的强制标准,而 h2c事实上被主流浏览器废弃。浏览器
使用 http2.0 的条件tomcat
- Nginx 版本大于或等于 1.9.5 。
- openssl 版本 等于或者大于OpenSSL 1.0.2
- 编译的时候开启
--with-http_v2_module
咱们这里配置的 h2 ,由于 浏览器对 h2c 基本不支持。服务器
Nginx 在 1.9.5 才开始引入 http2.0 ,官方日志。
编译的时候加入 --with-http_v2_module
,而后在 Nginx 配置中加上 http2
示例
listen 443 ssl http2 default_server;
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
看了下 8.0 版本, 是不支持 HTTP2.0
。
看了下 8.5版本, 是支持 HTTP2.0
。
怕上面文档没有看清,下面文中的 h2 指的是(基于TLS/1.2或以上版本的加密链接),h2c 是非加密的
非加密的,用浏览器是访问不了的(由于如今浏览器如今不支持),只支持 h2 。
官方文档写到
Tomcat 是支持 h2
和 h2c
的。 (你服务端支持没有用啊,客户端不支持,这不就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.
须要安装 openssl
版本大于或者等于1.0.2
。
yum install openssl
也就加 <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 . 第二条日志也就证明了。
也就意味着要进行配置证书了,
这个是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。
须要安装 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
参考文章: http://www.javashuo.com/article/p-airwqfse-cu.html
查看咱们的浏览器是否支持 http2.0, 打开网址进行测试。
网址, 须要越墙。
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支持。
默认使用 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 的话,须要作到如下几点