tomcat配置gzip压缩compressionMinSize选项无效

配置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形式帮你返回消息,响应肯定是要被压缩的。

  1. 大岩不灿说道:

    还有设置Content-Type一定要在写消息体之前指定,否则当你写的消息体大于缓冲区大小,或者是你执行了flush,消息体已经开始往外写了,再补充消息头header,已经来不及了。

留言

提示:你的email不会被公布,欢迎留言^_^

*

验证码 *