Spring Boot Enable Gzip

Tim
May 23, 2021

--

Application.propreties 設定

範例:

server.compression.enabled=true
server.compression.mime-types=application/json
server.compression.min-response-size=1024

並不是所有的response都需要做gzip ,所以會配置mine-types、min-response-size ,針對指定的型別、大小才做。

其他設定細節可參考 這邊

min-response-size constraint not working

這邊特別記錄一下實作過程遇到的一個有趣的問題,明明有設定min-response-size,但無論回傳大小多少,它都幫忙做了壓縮,這是為何?

檢查reponse header “Content-Length”

如果在你的response header中找不到,試試看找 “Transfer-Encoding=chunked”。 如果有表示這次回傳的大小並無法事前得知,而這正是為何無論怎麼設定min-response-size都無法成功生效的原因。

encoding chunked 詳細參考

為何沒有Content-Length會讓min-response-size設定失效?

參考CompressionConfig,這邊會決定這次reponse是否要進行壓縮處理,而我們可以看到裡面其中某項判斷

CompressionConfig.useCompression

要有明確的contentLength並且要大於我們設定的最小壓縮值,才會進行壓縮,而chunked encoded正式讓這邊contentLength = -1的主因。

確認response type

回傳的資料型態是下列何者?

  1. DetailInfoDto (Json Type)
  2. String

如果你今天是 1 的請往下看,或許可以幫到你

HttpMessageConverter

AbstractHttpMessageConverter會根據今天實際上使用的MessageConverter去判斷要不要加入Content-Length

AbstractHttpMessageConverter.addDefaultHeaders

對應兩種reponse type分別需要看到

  • Jackson2HttpMessageConverter
  • StringHttpMessageConverter
Jackson2HttpMessageConverter
StringHttpMessageConverter

這邊可以看到只有StringHttpMessageConverter有真的去計算出內容長度,而Json的就只是呼叫了super.getContentLength而後面實際上執行的內容如下,造成Json reponse的Content-Length=Null。

AbstractHttpMessageConverter

所以目前最快的方式,直接將reponse改為json string ,讓它選擇使用StringHttpMessageConverter,這樣後面的CompressionConfig則可以根據正確的Content-Length判斷是否超過設定的最小壓縮值,決定是否對回傳內容進行壓縮。

或者是在回傳Json前,先計算內容長度,並將header設定好,但就相對的多了一些步驟,比較容易忘記。

結論

當MessageConverter沒有設定Content-Length時,且Gzip開啟的狀態下,只要Content-Type對了,無論大小一律進行壓縮。

Gzip是否生效主要看下列三點是否滿足

  • config compression enabled
  • content-type matched
  • content-length is unknown or over threshold

--

--

Tim
Tim

No responses yet