09、Fegin 开启日志打印、Gzip压缩

日志打印

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,可以看到请求、响应消息头,都添加了压缩的相关标识。
&nbsp;
那么具体到底有没有压缩呢,由于压缩是客户端、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,说明确实进行了压缩处理。
&nbsp;

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客户端使用“透明”压缩,也是就默认就开启了压缩。。。啥都不用配。
&nbsp;
为了验证这一点,首先将账户服务中的压缩配置都关闭掉,只在订单服务中添加响应压缩支持。
&nbsp;
然后Dubug 到订单服务,可以看到请求头中,自动添加了压缩消息头,最后也是使用压缩返回了数据,直接使用Okhttp 时,不用再进行任何压缩配置了…。
&nbsp;