【OpenFeign】 Gzip 压缩
【OpenFeign】 Gzip 压缩
Metadata
title: 【OpenFeign】 Gzip 压缩
date: 2023-01-02 19:27
tags:
- 行动阶段/完成
- 主题场景/组件
- 笔记空间/KnowladgeSpace/ProgramSpace/ModuleSpace
- 细化主题/Module/OpenFeign/功能
categories:
- OpenFeign
keywords:
- OpenFeign
description: 【OpenFeign】 Gzip 压缩
Gzip 概述
gzip 是一种数据格式,采用 deflate 算法压缩数据,是一种流行的文件压缩算法,应用十分广泛,尤其是在 Linux 平台。
当 Gzip 压缩—个纯文本文件时,效果是非常明显的,大约可以减少 70% 以上的文件大小。
在网络数据经过压缩后实际上降低了网络传输的子节数,最明显的好处就是可以加快网页加载的速度。网页加载可以节省流量,改善用户的浏览体验。
HTTP 协议支持压缩说明
客户端向服务器发送请求时,如果消息头带有: Accept-Encoding:gzip, deflate
字段,表示客户端支持的压缩格式 (gzip 或者 deflate),如果不发送该消息头,服务端默认是不会压缩的。
服务端在收到请求之后,如果发现请求头中含有Accept-Encoding
字段,并且支持该类型压缩,就会对响应报文压缩之后返回给客户端,并且携带Content-Encoding:gzip
消息头,表示响应报文是根据该格式进行压缩的。
客户端接收到请求之后,先判断是否有Content-Encoding
消息头,如果有,按该格式解压报文。否则按正常报文处理。
但是使用 GZIP 要增加服务器压缩的压力(cpu 消耗)、客户端解压缩的压力。
Tomcat 使用 Gzip 压缩
Spring Boot 在使用 Tomcat 时,可以直接通过配置开启 Gzip 压缩。
对应的配置类为Compression
:
- enabled : 是否开启压缩,默认 false
- mimeTypes : 压缩的媒体类型,默认是 JSON、页面等数据会进行压缩
- excludedUserAgents :哪些浏览器访问时进行压缩
- minResponseSize :响应数据最小多大,才压缩,默认 2K
public class Compression {
private boolean enabled = false;
private String[] mimeTypes = new String[]{"text/html", "text/xml", "text/plain", "text/css", "text/javascript", "application/javascript", "application/json", "application/xml"};
private String[] excludedUserAgents = null;
private DataSize minResponseSize = DataSize.ofKilobytes(2L);
}
可以在 YML 中开启压缩功能:
server:
port: 9002
compression:
enabled: true
测试:编写一个返回大数据量的访问接口。
@GetMapping("/gzip")
public Object gzip() {
// 模拟给当前账户下单
List<Account> list=new ArrayList<>();
for (long i = 0L; i < 10000L; i++) {
Account account=new Account();
account.setAccountId(i);
list.add(account);
}
return list;
}
F12,可以看到请求、响应消息头,都添加了压缩的相关标识。
那么具体到底有没有压缩呢,由于压缩是客户端、WEB 服务器自己进行的,程序员无法感知。我们可以直接 Debug 到 Tomcat 的源码中,查看响应数据时,到底有没有进行压缩。
我们 Debug 到Http11Processor
类的prepareResponse()
方法,该类是 tomcat 中用于处理 http 请求的 Processor 的实现类,看下他的压缩处理逻辑:
boolean useCompression = false;
// 判断是否进行压缩
if (entityBody && this.sendfileData == null) {
useCompression = this.protocol.useCompression(this.request, this.response);
}
可以看到最后,useCompression
变量为 true,说明确实进行了压缩处理。
Fegin 使用 Gzip 压缩
Fegin
是基于服务之前远程调用,所以不会像浏览器一样,请求自动添加压缩格式的支持。
Fegin
压缩对应的配置类为FeignClientEncodingProperties
,配置属性和 Tomcat 中的一个意思。
@ConfigurationProperties("feign.compression.request")
public class FeignClientEncodingProperties {
private String[] mimeTypes = new String[]{"text/xml", "application/xml", "application/json"};
private int minRequestSize = 2048;
}
然后看下压缩自动配置类FeignAcceptGzipEncodingAutoConfiguration
,实际上就是注入了一个请求拦截器,在请求头中添加Accept-Encoding:gzip, deflate"
,但是在@ConditionalOnMissingBean
中,如果使用的是 okhttp3 框架,则不会加载这个配置(那为啥用 okhttp 时,不会配置压缩呢?)。
@ConditionalOnProperty(
value = {"feign.compression.response.enabled"},
matchIfMissing = false
)
@ConditionalOnMissingBean(
type = {"okhttp3.OkHttpClient"}
)
@AutoConfigureAfter({FeignAutoConfiguration.class})
public class FeignAcceptGzipEncodingAutoConfiguration {
public FeignAcceptGzipEncodingAutoConfiguration() {
}
@Bean
public FeignAcceptGzipEncodingInterceptor feignAcceptGzipEncodingInterceptor(FeignClientEncodingProperties properties) {
// 添加压缩拦截器
// this.addHeader(template, "Accept-Encoding", new String[]{"gzip", "deflate"});
return new FeignAcceptGzipEncodingInterceptor(properties);
}
}
在源码中有说明: OK HTTP 客户端使用 “透明” 压缩,也是就默认就开启了压缩。。。啥都不用配。
为了验证这一点,首先将账户服务中的压缩配置都关闭掉,只在订单服务中添加响应压缩支持。
然后 Dubug 到订单服务,可以看到请求头中,自动添加了压缩消息头,最后也是使用压缩返回了数据,直接使用 Okhttp 时,不用再进行任何压缩配置了…。