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
了: