Tomcat9配置HTTP/2

1 概述

Tomcat從Tomcat8的一些較新版本就支持HTTP/2了,Tomcat9直接支持,本文首先講述了相關HTTP/2的特性,接着利用一個簡單的開源工具mkcert生成證書並利用該證書配置HTTP/2。

2 HTTP/2特性

首先介紹一下HTTP/2特性,這也從另一方面解釋了爲什麼需要使用HTTP/2。

2.1 二進制分幀

HTTP/2在應用層與傳輸層增加了一個二進制分幀,能夠達到“在不改動HTTP語義,HTTP方法,狀態碼,URI及首部字段的情況下,突破HTTP/1.1的性能限制,改進傳輸性能,實現低延遲和高吞吐量。”

2.2 壓縮頭部

HTTP/2對消息頭採用了HPACK進行壓縮傳輸,能夠節省消息頭佔用的網絡流量,而HTTP/1.x每次請求都會攜帶大量的冗餘頭信息,浪費了很多帶寬資源。

2.3 多路複用

簡單地說就是所有的請求都通過一個TCP連接併發完成。HTTP/1.x雖然能利用一個連接完成多次請求,但是多個請求之間是有先後順序的,後面發送的請求必須等待上一個請求返回才能發送響應,很容易導致後面的請求被阻塞。而HTTP/2做到了真正的併發請求。
HTTP/2將消息分解爲幀,爲每幀分配一個流標識符,然後在一個TCP連接上獨立發送,HTTP/2將請求幀與響應幀交織在一起,能夠讓所有請求與響應都在一個套接字上發生,所有請求或響應都無法相互阻塞,減少了延遲,提高了頁面加載速度,消除了對HTTP/1.1工具的需求。

2.4 流優先及流控制

消息幀通過對流進行發送,每個流分配了一個優先級,用於確定處理順序以及收到的資源量,優先級可以是0-256之間的數字,可以定義依賴關係,允許在一個資源之前加載另一個資源。
流控制管理數據的傳輸,允許接收者停止或減少發送的數據量,比如觀看視頻暫停時,客戶端會通知服務器停止發送視頻數據。

2.5 服務器推送

一般情況下需要客戶端請求服務器纔會響應,HTTP/2中能夠先於客戶端檢測將要請求的資源,提前通知客戶端,但是不發送資源只發送URL,客戶端收到後會進行驗證緩存,發現需要則正式發起請求。

2.6 應用層協商協議

客戶端與服務器都升級才能支持HTTP/2,但是有可能存在HTTP/1與HTTP/2並存的情況,如果都使用80端口,需要選擇其中一個協議通信。
APLN(Application Layer Protocol Negotiation)就是爲了解決這個問題,通過協商選擇協議:

  • 首先客戶端發起請求,如果支持HTTP/2則帶upgrade頭部
  • 若服務器不支持則拒絕升級通過HTTP/1.1返回響應
  • 若服務器支持則接受升級,切換到新分幀使用HTTP/2通信

更多請查看RFC7540 官方文檔

3 使用mkcert生成證書

網上大部分的教程都是使用OpenSSL生成根證書,客戶端證書以及服務端證書的,一堆參數配置非常複雜,因此這裏使用一個簡單的一鍵生成本地證書的開源工具mkcert,無需任何配置。

3.1 安裝mkcert

3.1.1 MacOS

brew install mkcert
brew install nss # 如果使用火狐

使用MacPorts:

sudo port selftupdate
sudo port install mkcert
sudo port install css # 如果使用火狐

3.1.2 Linux

需要先安裝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)"

或者使用已構建好的版本

3.1.3 Windows

安裝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

或者使用已構建好的版本

3.2 生成證書

mkcert的命令非常簡單,可以使用--help查看幫助:

mkcert --help

3.2.1 安裝本地CA證書

mkcert -install

默認會在~/.local/share/mkcert生成CA證書。

3.2.2 利用CA證書籤發本地證書

mkcert localhost

其中localhost表示簽發本地證書,可以換成example.com*.example.comexample.test127.0.0.1::1之類的域名或者ip。
執行後會在當前文件夾下生成localhost-key.pemlocalhost.pem,前者是私鑰,後者是證書。

4 配置Tomcat

Tomcat可以通過兩種方式配置HTTP/2,一種是自帶的Nio方式,另一種是使用額外庫APR,APR-util與TC-Native的方式。

4.1 使用Nio

通過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
在這裏插入圖片描述
在這裏插入圖片描述

4.2 使用APR

使用APR不需要對證書進行額外的轉換,但是需要安裝三個庫:

筆者的Manjaro可以直接包管理器安裝:

sudo pacman -S apr apr-util tomcat-native

其他系統請自行使用包管理器或者按上面的官網鏈接進行編譯安裝。
複製localhost-key.pemlocalhost.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了:
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章