本文來源于項目需要,項目所使用微服務框架為Spring Cloud,微服務之間的調用基于HTTP 1.X協議,上一篇文章 HTTPS vs HTTP 1.1 vs HTTP 2,介紹了http2 和http1.1的相關知識,也列出了http1.1局限性,鏈路不能復用、數據不加密、頭信息過多等等。為此,筆者在想能不能將feign client的調用基于http2協議,做了如下調研。
HTTP/2 源自 SPDY/2。SPDY 系列協議由谷歌開發,于 2009 年公開。它的設計目標是降低 50% 的頁面加載時間。當下很多著名的互聯網公司,例如百度、淘寶、UPYUN 都在自己的網站或 APP 中采用了 SPDY 系列協議(當前最新版本是 SPDY/3.1),因為它對性能的提升是顯而易見的。主流的瀏覽器(谷歌、火狐、Opera)也都早已經支持 SPDY,它已經成為了工業標準,HTTP Working-Group 最終決定以 SPDY/2 為基礎,開發 HTTP/2。
2013年8月,進行首次測試,誕生的時間很晚,筆者搜索了網上關于http2實踐的相關信息,發現并不多。
Spring Cloud是筆者項目采用的微服務框架,具體介紹見Spring Cloud。Spring Cloud是基于Spring Boot開發的組合框架,Spring Boot內置的容器是Tomcat,筆者的項目一般都會exclude Tomcat的引用,使用的是Jetty容器。所以搜索的主題詞就變成了 jetty http2。
大部分的人習慣于將Tomcat運行在8080端口,再用Apache server在前面提供https。這樣做是因為簡單且驗證過的方法。使用http2 ,你將被迫使用https,這樣就不用部署Apache (or nginx)。
Currently Jetty and undertow are the only servers in Spring Boot that support HTTP/2.
Jetty has booked some progress and this repository shows an excellent example. In my opinion it’s still too much custom code, but they’re getting there.
The next candidate is undertow. It seems almost too easy, but it works. Because we use AJP in our current configuration it even means this HTTP/2 solution has less lines of code!
當前Spring Boot只有Jetty 和 undertow支持HTTP/2。 樣例repo是一個很好的example。
總得分為三步:
|
|
|
|
Currently Java HTTP/2 clients are scarce. According to this wiki Netty and OkHttp are the only two implementations supported by Spring. To switch HTTP-client in RestTemplate you have to call the constructor with a different ClientHttpRequestFactory (either Netty4ClientHttpRequestFactory or OkHttpClientHttpRequestFactory).
當前Java的http2的客戶端也很少,Spring只有Netty and OkHttp支持。這邊我們選用了OkHttp,因為OkHttp本來就有在feign client中內置。
|
|
通過瀏覽器支持http2查看。
目前, Http/1.1在全世界大范圍的使用中, 直接廢棄跳到http/2肯定不現實. 不是每個用戶的瀏覽器都支持http/2的, 也不是每個服務器都打算支持http/2的, 如果我們直接發送http/2格式的協議, 服務器又不支持, 那不是掛掉了! 總不能維護一個全世界的網站列表, 表示哪些支持http/2, 哪些不支持?
為了解決這個問題, 從稍高層次上來說, 就是為了更方便地部署新協議, HTTP/1.1 引入了 Upgrade 機制. 這個機制在 RFC7230 的「6.7 Upgrade」這一節中有詳細描述.
簡單說來, 就是先問下你支持http/2么? 如果你支持, 那么接下來我就用http/2和你聊天. 如果你不支持, 那么我還是用原來的http/1.1和你聊天.
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c
[ HTTP/2 connection … ]
HTTP Upgrade 響應的狀態碼是 101,并且響應正文可以使用新協議定義的數據格式。
這樣就可以完成從http/1.1升級到http/2了. 同樣也可以從http/1.1升級到WebSocket.
OkHttp使用了請求協議的協商升級, 無論是1.1還是2, 都先只以1.1來發送, 并在發送的信息頭里包含協議升級字段. 接下來就看服務器是否支持協議升級了. OkHttp使用的協議升級字段是ALPN, 如果有興趣, 可以更深入的查閱相關資料.
總體看來,現在Spring boot 是可以支持HTTP/2 server和client。現有項目的api接口面向移動端和web端,web瀏覽器對于http2的支持在上文已經說明。
參考資料:
OkHttp使用完全教程
Spring Boot with HTTP/2 – Start a server and make REST calls as a client
HTTPS 與 HTTP2 協議分析