背景
当我们一个接口响应报文比较大的时候,超过几兆甚至几十兆的情况下,减少响应体的报文大小是能有效减少响应时间的。
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的好处比较多: