背景
當我們一個接口響應報文比較大的時候,超過幾兆甚至幾十兆的情況下,減少響應體的報文大小是能有效減少響應時間的。
spring boot 配置
server:
compression:
## 開啓服務端的報文壓縮
enabled: true
## 只壓縮響應類型爲application/json的報文
mime-types: application/json
## 觸發壓縮報文的最小響應體大小,默認2048字節(2KB)
min-response-size: 2048
默認配置爲:
光服務端配置好還不能保證服務端的響應報文被壓縮,還有以下流程:
-
客戶端(瀏覽器)的請求頭(request header)需要帶上參數字段 Accept-Encoding :gzip, deflate
-
服務端的響應頭(response header)返回參數字段 Content-Encoding : gzip
-
客戶端按照定好的格式進行報文解壓工作。
-
開啓壓縮前
-
開啓壓縮後
開啓feign請求響應報文壓縮
配置
feign:
compression:
request:
## 開啓feign請求壓縮
enabled: true
## 壓縮報文類型
mime-types: text/xml,application/xml,application/json
## 請求體大於2048字節則開啓
min-request-size: 2048
response:
## 開啓feign請求壓縮
enabled: true
## 使用gzip解碼
useGzipDecoder: true
默認配置爲:
實現源碼
-
如果開啓feign響應壓縮,則添加feign請求攔截器,並在請求頭中添加字段 Accept-Encoding :gzip, deflate
-
如果開啓feign請求壓縮,則添加feign請求攔截器,判斷需要的響應體類型、請求體大小判斷是否讓響應體開啓gzip報文壓縮。
避坑指南
當項目中開啓了OkHttpClient時,會讓feign.compression 配置失效。
我們項目中,有位已離職的同事寫了這個配置,導致我們feign開啓gzip一直失敗、報錯。
@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignOkHttpConfig {
@Bean
public okhttp3.OkHttpClient okHttpClient(){
return new okhttp3.OkHttpClient.Builder()
//設置連接超時
.connectTimeout(10, TimeUnit.SECONDS)
//設置讀超時
.readTimeout(10, TimeUnit.SECONDS)
//設置寫超時
.writeTimeout(10,TimeUnit.SECONDS)
//是否自動重連
.retryOnConnectionFailure(true)
.connectionPool(new ConnectionPool())
//構建OkHttpClient對象
.build();
}
}
如果非得用okHttp,並支持feign請求壓縮,則需要自己去嘗試實現。
- 開啓OkHttp,並關閉 httpClient
feign:
httpclient:
enabled: false
okhttp:
enabled: true
-
okHttp有一套自己的玩法,
調試過程中,發現開啓okHttp後,httpClient的代理失效了,因此我就不在往下探索了。
可能需要自己配置 gzip encoder、gzip decoder,還有攔截器配置,感覺比較麻煩。 -
結論
因此springboot項目中如果要開啓gzip響應,最終還是不使用okHttp,減少接入複雜度、學習成本。
即使okhttp的好處比較多: