配置tomcat的gzip压缩功能之后,配置有个compressionMinSize选项,表示压缩响应的最小值,只有当响应报文大小大于这个值的时候才会对报文进行压缩。但是有时候你会发现这个配置并不起作用,貌似只要客户端加了Accept-Encoding: gzip, deflate,响应就是压缩的,无论响应报文体有多大,这是怎么回事呢?
查看tomcat源码,关于压缩条件控制的地方:org.apache.coyote.http11.AbstractHttp11Processor类中:
1 2 3 4 5 6 7 8 9 10 | // Check if sufficient length to trigger the compression long contentLength = response.getContentLengthLong(); if ((contentLength == -1) || (contentLength > compressionMinSize)) { // Check for compatible MIME-TYPE if (compressableMimeTypes != null) { return (startsWithStringArray(compressableMimeTypes, response.getContentType())); } } |
可以看到,tomcat判断是否压缩的的依据是根据你响应里的Content-length来的,如果没有Content-length或者Content-length大于compressionMinSize就进行压缩。如果你的报文小于compressionMinSize,却被压缩了,那就是你的响应报文中并不含有Content-length。
Content-length可以在往外写响应流之前手动设置,如果你不设置的话,在关闭响应流的时候,如果你的响应体没超过tomcat默认缓存区大小8*1024,它也会帮你设置Content-lenth,如果超过了缓存区大小,tomcat会以Transfer-Encoding: chunked的形式返回响应。
所以如果你的设置compressionMinSize的没有生效,很有可能是
你的设置的compressionMinSize超出了tomcat的缓冲区大小,响应默认是chunked的形式返回的,这种情况是肯定压缩的。这种情况,还是有部分响应<8k的响应是不压缩的。
如果你的响应无论什么大小都被压缩了,那很有可能就是你在代码中使用了OutputStream.flush(),或者PrintWriter.flush()。使用flush()的意思是响应开始往外写了,Content-length已经来不及写了,tomcat会默认使用Transfer-Encoding: chunked形式帮你返回消息,响应肯定是要被压缩的。
除非注明,赵岩的博客文章均为原创,转载请以链接形式标明本文地址
本文地址:https://zhaoyanblog.com/archives/652.html
还有设置Content-Type一定要在写消息体之前指定,否则当你写的消息体大于缓冲区大小,或者是你执行了flush,消息体已经开始往外写了,再补充消息头header,已经来不及了。