如何讓Spring boot 2.0 支持h2c協(xié)議

前面有文章介紹了Spring boot 2.0 中配置實(shí)現(xiàn)HTTP/2協(xié)議的各種情形芽唇,但是其中介紹都是h2協(xié)議肌厨。HTTP/2協(xié)議有兩個版本:h2h2c斋泄,h2ch2 的明文版本昆婿,沒有建立在TLS基礎(chǔ)上,沒有安全保障撞蜂。正是因為沒有TLS層的加解密相關(guān)步驟盲镶,比較適合用在后端服務(wù)之間通信,gRPC就是同時支持這兩個版本的HTTP/2協(xié)議蝌诡。

00 前言

HTTP/2連接是建立在TCP連接之上的應(yīng)用層協(xié)議溉贿,客戶端是TCP連接的發(fā)起者。

HTTP/2使用和HTTP/1.1一樣的 URI schemes:"http" 和 "https"浦旱,并且還是共享同樣的默認(rèn)端口:http的80宇色,https的443。這意味著颁湖,對于"http" 和 "https"確定其是否支持HTTP/2協(xié)議的方式是不同的宣蠕。

官方文檔中,為HTTP/2協(xié)議定義了兩個版本:h2h2c

  • h2版本的協(xié)議是建立在TLS層之上的HTTP/2協(xié)議甥捺,這個標(biāo)志被用在TLS應(yīng)用層協(xié)議協(xié)商(TLS-ALPN)域和任何其它的TLS之上的HTTP/2協(xié)議植影。
  • h2c版本是建立在明文的TCP之上的HTTP/2協(xié)議,這個標(biāo)志被用在HTTP/1.1的升級協(xié)議頭域和其它任何直接在TCP層之上的HTTP/2協(xié)議涎永。

既然在HTTP/2協(xié)議的官方介紹中有兩個版本,我們之前的文章介紹的是Spring boot 2.0如何實(shí)現(xiàn)h2鹿响,本文我們會介紹如何讓Spring boot 2.0支持h2c協(xié)議羡微。

01 Spring boot 2.0 h2c協(xié)議服務(wù)端

由于h2c協(xié)議相對于h2來說簡單些,應(yīng)該要實(shí)現(xiàn)也不難惶我,但是從Spring boot 2.0的官方文檔上看妈倔,明確寫明了“Spring boot 不支持h2c —— HTTP/2協(xié)議的明文版本”,于是就想其它辦法來支持h2c绸贡。

首先盯蝴,想的是通過外置的tomcat配置來支持h2c,因為tomcat8.5中的server.xml配置中听怕,有HTTP/2協(xié)議相關(guān)的配置:

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

這里顯示要添加證書捧挺,明顯支持的是基于TLS層之上的h2版本的HTTP/2協(xié)議,但是從配置上可以禁用SSL尿瞭,于是就嘗試了一下闽烙,果然成功了。配置成如下示例声搁,就支持h2c了:

<Connector port="5080" protocol="HTTP/1.1" connectionTimeout="20000">
    <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
</Connector>

tomcat容器自身是支持多個connector的配置的黑竞,想到這里捕发,就想在Spring boot 2.0 中是否支持同時配置多個Connector,查看Spring boot的官方文檔發(fā)現(xiàn)如下配置:

Spring boot 2.0 tomcat Connector

文檔中示例是通過 java configure 的方式配置一個https的connector很魂,在application.yaml中不支持配置多個connector扎酷。

因此我就模仿這外置tomcat配置h2c的方式,在Spring boot 2.0 的內(nèi)置tomcat中通過java configure的方式配置h2c協(xié)議遏匆,具體代碼如下:

@Bean
public ServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    tomcat.addAdditionalTomcatConnectors(createH2cConnector());
    return tomcat;
}

private Connector createH2cConnector() {
    Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    Http2Protocol upgradeProtocol = new Http2Protocol();
    connector.addUpgradeProtocol(upgradeProtocol);
    //connector.setScheme("http");
    connector.setPort(5080);

    return connector;
}

這時啟動我們的Spring boot應(yīng)用法挨,會發(fā)現(xiàn)最后的啟動日志,我們同時啟動三個端口拉岁,也即是三個Connector:

Tomcat started on port(s): 8080 (http) 8443 (https) 5080 (http) with context path '/demo-h2c'

02 Curl 工具驗證h2c協(xié)議服務(wù)端

首先需要檢查你的curl工具是否支持HTTP/2協(xié)議坷剧,驗證方式:

?  ~ curl -V
curl 7.54.0 (x86_64-apple-darwin17.0) libcurl/7.54.0 LibreSSL/2.0.20 zlib/1.2.11 nghttp2/1.24.0
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz HTTP2 UnixSockets HTTPS-proxy

從上面的 Features 信息發(fā)現(xiàn),我的curl工具是支持HTTP/2協(xié)議的喊暖。

下面開始驗證我Spring boot 的服務(wù)在5080端口是否是h2c惫企,具體如下:

?  ~ curl -v --http2 http://127.0.0.1:5080/demo-h2c/h2c/hello\?name\=guoyankui
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 5080 (#0)
> GET /demo-h2c/h2c/hello?name=guoyankui HTTP/1.1
> Host: 127.0.0.1:5080
> User-Agent: curl/7.54.0
> Accept: */*
> Connection: Upgrade, HTTP2-Settings
> Upgrade: h2c
> HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA
>
< HTTP/1.1 101
< Connection: Upgrade
< Upgrade: h2c
< Date: Sun, 06 May 2018 13:12:37 GMT
* Received 101
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< content-type: text/plain;charset=UTF-8
< date: Sun, 06 May 2018 13:12:37 GMT
<
* Connection #0 to host 127.0.0.1 left intact
Hello h2c: null%

OK, 驗證通過了。

03 支持h2c協(xié)議的java客戶端

在上一節(jié)中使用Curl工具驗證了Spring boot 2.0 的服務(wù)的h2c協(xié)議陵叽,但是在java語言中狞尔,還需要有支持h2c的Java客戶端。目前一般的 java 客戶端都只是支持h2巩掺,有的還不支持HTTP/2協(xié)議偏序,而且瀏覽器一般也不支持h2c。

現(xiàn)在找到一個支持h2c的java客戶端也不容易胖替,目前找到okhttp3的最新版本3.10.0也不支持h2c研儒,但是發(fā)現(xiàn)在最新的github代碼中3.11.0-SNAPSHOT版本已經(jīng)支持了h2c,代碼示例:

public static void main(String[] args) throws Exception {
    testH2C();
}

public static void testH2C() throws Exception {
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .protocols(Arrays.asList(Protocol.H2C))
            .build();

    Request request = new Request.Builder()
            .url("http://127.0.0.1:5080/demo-h2c/h2c/hello?name=guoyankui")
            .build();
    Response response = okHttpClient.newCall(request).execute();
    System.out.println(response.protocol());
    System.out.println(response.body().string());
}

執(zhí)行這個main函數(shù)之后独令,輸出的結(jié)果:

h2c
Hello h2c: guoyankui

從輸出的結(jié)果來看端朵,驗證了h2c協(xié)議的客戶端和服務(wù)端。

04 結(jié)束

目前燃箭,找到了okhttp3的3.11.0版本支持h2c冲呢,有支持h2c的Java 客戶端了,我們也在Spring boot 2.0中實(shí)現(xiàn)了h2c的服務(wù)端招狸,因此也算有了支持h2c協(xié)議的完整方案敬拓。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市裙戏,隨后出現(xiàn)的幾起案子乘凸,更是在濱河造成了極大的恐慌,老刑警劉巖挽懦,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翰意,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)冀偶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門醒第,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人进鸠,你說我怎么就攤上這事稠曼。” “怎么了客年?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵霞幅,是天一觀的道長。 經(jīng)常有香客問我量瓜,道長司恳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任绍傲,我火速辦了婚禮扔傅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘烫饼。我一直安慰自己猎塞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布杠纵。 她就那樣靜靜地躺著荠耽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪比藻。 梳的紋絲不亂的頭發(fā)上铝量,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機(jī)與錄音银亲,去河邊找鬼款违。 笑死,一個胖子當(dāng)著我的面吹牛群凶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哄辣,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼请梢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了力穗?” 一聲冷哼從身側(cè)響起毅弧,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎当窗,沒想到半個月后够坐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年元咙,在試婚紗的時候發(fā)現(xiàn)自己被綠了梯影。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡庶香,死狀恐怖甲棍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赶掖,我是刑警寧澤感猛,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站奢赂,受9級特大地震影響陪白,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜膳灶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一咱士、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袖瞻,春花似錦司致、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至霉晕,卻和暖如春庭再,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牺堰。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工拄轻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伟葫。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓恨搓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親筏养。 傳聞我的和親對象是個殘疾皇子斧抱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容