天天看點

spring rest 容易被忽視的後端服務 chunked 性能問題spring boot 容易被忽視的後端服務 chunked 性能問題

标簽(空格分隔): springboot springmvc chunked

背景

spring boot 建立的預設 spring mvc 項目

內建 JAX-RS 規範架構 Jersey

在之前的一次性能壓測的時候我們發現一個細節問題,我們使用 spring boot 建立的 web rest 項目,使用預設 spring mvc 作為 web rest 架構。

這在使用上沒有太大問題,但是有一個影響性能的細節問題被發現了,說實話這個問題很難被發現。

我們來看一個簡單的 demo,我使用 IDEA 建立一個 spring boot 項目,建立過程中沒有什麼特别的選項需要調整,一路 next 。然後我們建立一個簡單的 controller 。

再建立一個簡單的 model 。

然後啟動通路這個 controller ,注意看下傳回的 http 資訊裡多了一個 Transfer-Encoding:chunked 。Transfer-Encoding:chunked 在 HTTP 協定裡的意思是無法計算 Content-Length 長度,需要分塊傳輸。

這是 spring mvc 的預設 complex object 傳輸方式,如果我們傳回的是一個簡單的對象就不會有這個問題。

Transfer-Encoding:chunked 帶來的性能問題就是通路一次資料在 __http__層面看确實是一次 http 請求,而通過 tcp 抓包工具檢視會發現多了一次 tcp 傳輸。

解決這個問題兩個層面都可以,一種是采用比較粗暴的方式在 servlet 容器層面解決,但是這個會帶來一個後果就是當我們計算 complex object 大小的時候會比較複雜而且容易出錯,也會影響項目未來的分塊傳輸功能,效果不太好。

還有一種就是在應用層面解決,比較柔性也易于擴充,我們可以內建一個 rest 架構,最好是符合 JAX-RS 規範,本文我們內建 Jersey 架構。

spring boot 解決了以前 spring 繁重的配置,提供了 auto config 功能,原來通過 web.xml 配置 servlet 的,現在需要用代碼來配置。spring boot 提供了讓我們手動注冊 servlet bean 的方式。

ServletRegistrationBean 可以讓我們注冊servlet,我們來看下完整代碼。

這和原來在 web.xml 配置的是一樣的,設定 routing 位址,設定 Init 初始化參數,對應的 servlet class name 。

所有的 __"rest/v1/*"__ 請求都将被 ServletContainer jersey servlet 容器接管。

ResourceConfig 其實是一個 jersey Application 類型。這是 __jersey 注冊 servlet 時規定的。

這是我們應用代碼 Controller ,使用 JAX-RS 規範的注解進行設定即可。

這樣就解決了 sprng mvc 和 jersey rest 共同存在的問題,我們也不需要将所有的傳回 chunked 的接口都改成 JAX-RS 的 rest 服務,隻需要将有性能瓶頸的接口改造下即可。