日志打印
Logger 日志类
Feign 可以开启请求响应详细日志打印,方便我们调试程序,在构建客户端、方法执行器的时候,都可以看到设置了日志类及日志级别。
该Logger
是Feign 自己提供的类,该日志类,提供了打印请求日志、响应日志、IO异常、重试日志等方法。
该类还提供了一个日志级别:
public static enum Level {
// 不输出日志(默认)
NONE,
// 输出请求方法、URL、响应状态码、执行时间
BASIC,
// 基本信息以及请求和响应头
HEADERS,
// 所有=》请求和响应的heads、body、metadata
FULL;
private Level() {
}
}
使用案例
使用的话,我们需要在配置类中声明日志级别:
@Bean
Logger.Level feignLevel() {
return Logger.Level.FULL;
}
然后在YML 中配置当前Feign 客户端接口的日志级别为debug:
logging:
level:
account.OrderFeign: debug
然后查看日志,可以看到请请求路径、消息头、响应消息什么的都打印出来了:
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 时,不用再进行任何压缩配置了…。