Tomcat从Tomcat8的一些较新版本就支持HTTP/2了,Tomcat9直接支持,本文首先讲述了相关HTTP/2的特性,接着利用一个简单的开源工具mkcert生成证书并利用该证书配置HTTP/2。css
首先介绍一下HTTP/2特性,这也从另外一方面解释了为何须要使用HTTP/2。html
HTTP/2在应用层与传输层增长了一个二进制分帧,可以达到“在不改动HTTP语义,HTTP方法,状态码,URI及首部字段的状况下,突破HTTP/1.1的性能限制,改进传输性能,实现低延迟和高吞吐量。”git
HTTP/2对消息头采用了HPACK进行压缩传输,可以节省消息头占用的网络流量,而HTTP/1.x每次请求都会携带大量的冗余头信息,浪费了不少带宽资源。github
简单地说就是全部的请求都经过一个TCP链接并发完成。HTTP/1.x虽然能利用一个链接完成屡次请求,可是多个请求之间是有前后顺序的,后面发送的请求必须等待上一个请求返回才能发送响应,很容易致使后面的请求被阻塞。而HTTP/2作到了真正的并发请求。
HTTP/2将消息分解为帧,为每帧分配一个流标识符,而后在一个TCP链接上独立发送,HTTP/2将请求帧与响应帧交织在一块儿,可以让全部请求与响应都在一个套接字上发生,全部请求或响应都没法相互阻塞,减小了延迟,提升了页面加载速度,消除了对HTTP/1.1工具的需求。apache
消息帧经过对流进行发送,每一个流分配了一个优先级,用于肯定处理顺序以及收到的资源量,优先级能够是0-256之间的数字,能够定义依赖关系,容许在一个资源以前加载另外一个资源。
流控制管理数据的传输,容许接收者中止或减小发送的数据量,好比观看视频暂停时,客户端会通知服务器中止发送视频数据。缓存
通常状况下须要客户端请求服务器才会响应,HTTP/2中可以先于客户端检测将要请求的资源,提早通知客户端,可是不发送资源只发送URL,客户端收到后会进行验证缓存,发现须要则正式发起请求。tomcat
客户端与服务器都升级才能支持HTTP/2,可是有可能存在HTTP/1与HTTP/2并存的状况,若是都使用80端口,须要选择其中一个协议通讯。
APLN(Application Layer Protocol Negotiation)就是为了解决这个问题,经过协商选择协议:bash
更多请查看RFC7540 官方文档。服务器
网上大部分的教程都是使用OpenSSL生成根证书,客户端证书以及服务端证书的,一堆参数配置很是复杂,所以这里使用一个简单的一键生成本地证书的开源工具mkcert,无需任何配置。网络
brew install mkcert brew install nss # 若是使用火狐
使用MacPorts:
sudo port selftupdate sudo port install mkcert sudo port install css # 若是使用火狐
须要先安装certutil
:
#Debian/Ubuntu sudo apt install libnss3-tools #Red Hat/Fedora/CentOS sudo yum install nss-tools #Arch/Manjaro sudo pacman -S nss #SUSE sudo zypper install mozilla-nss-tools
使用LinuxBrew
安装:
brew install mkcert
安装LinuxBrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
Arch/Manjaro可使用pacman安装:
sudo pacman -Syu mkcert
或者从源码安装(须要go环境):
git clone https://github.com/FiloSottile/mkcert && cd mkcert go build -ldflags "-X main.Version=$(git describe --tags)"
或者使用已构建好的版本。
安装Chocolatey(以管理员运行PowerShell):
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
或安装Scoop(管理员PowerShell):
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') # 或 iwr -useb get.scoop.sh | iex
使用Chocolatey或Scoop安装:
choco install mkcert #或 scoop bucket add extras scoop install mkcert
或者使用已构建好的版本。
mkcert的命令很是简单,可使用--help
查看帮助:
mkcert --help
mkcert -install
默认会在~/.local/share/mkcert
生成CA证书。
mkcert localhost
其中localhost表示签发本地证书,能够换成example.com
,*.example.com
,example.test
,127.0.0.1
,::1
之类的域名或者ip。
执行后会在当前文件夹下生成localhost-key.pem
与localhost.pem
,前者是私钥,后者是证书。
Tomcat能够经过两种方式配置HTTP/2,一种是自带的Nio方式,另外一种是使用额外库APR,APR-util与TC-Native的方式。
经过Nio配置HTTP/2须要结合OpenSSL与keytool将证书转换为pkcs#12
再转换为jks
:
openssl pkcs12 -export -inkey localhost-key.pem -in localhost.pem -out localhost.p12
会提示输入导出密码,须要记住,转换成jks
时须要用到。
接着转换为jks
:
keytool -importkeystore -srckeystore localhost.p12 -srcstoretype pkcs12 -destkeystore localhost.jks
这里会提示输入目标keystore与源keystore的密码,目标keystore密码一会在修改server.xml
时须要用到,源keystore密码就是上面的导出密码。
接着复制localhost.jks
到Tomcat的conf
下并修改server.xml
:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" SSLEnabled="true"> <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> <SSLHostConfig> <Certificate certificateKeystoreFile="conf/localhost.jks" certificateKeystorePassword="111111" type="RSA" /> </SSLHostConfig> </Connector>
添加了升级协议(默认HTTP/1.1):
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
另外certificateKeystorePassword
是上一步的目标keystore的密码。
完成后开启Tomcat并访问https://localhost:8443
:
使用APR不须要对证书进行额外的转换,可是须要安装三个库:
笔者的Manjaro能够直接包管理器安装:
sudo pacman -S apr apr-util tomcat-native
其余系统请自行使用包管理器或者按上面的官网连接进行编译安装。
复制localhost-key.pem
与localhost.pem
到Tomcat的conf
目录下,并修改server.xml
:
<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-key.pem" certificateFile="conf/localhost.pem" type="RSA" /> </SSLHostConfig> </Connector>
开启Tomcat后就能够访问https://localhost:8443
了: