高性能Tomcat配置之开启GZIP压缩

原创 tomcatgzip

GZIP压缩原理

GZIP压缩可以大大提高浏览网站的速度,它的原理是,在客户端请求服务器对应资源后,从服务器端将资源文件压缩,再输出到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的浏览过程HTML,CSS,Javascript,Text,它可以节省40%左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP,JSP,ASP,Servlet,SHTML等输出的网页也能进行压缩,压缩效率也很高。

TOMCAT启用GZIP压缩配置方法

从Tomcat5.0以后的版本,是支持对输出内容进行压缩的,使用的是gzip压缩格式。修改%TOMCAT_HOME%/conf/server.xml,修订节点如下:

<Connector port="80" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8443" executor="tomcatThreadPool" URIEncoding="utf-8" 
               compression="on" 
               compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata"
        compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" />

从上面节点的属性可以看出,要使用gzip压缩功能,你需要在Connector节点中加上如下属性:

// 打开压缩功能
compression="on"
// 启用压缩的输出内容大小,默认为2KB
compressionMinSize="2048"
// 对于以下的浏览器,不启用压缩
noCompressionUserAgents="gozilla, traviata"
// 哪些资源类型需要压缩
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"

需要注意的是,tomcat从7.0之后,把JavaScript的mime类型更改为application/javascript了。

mime类型可以在%TOMCAT_HOME%/conf/web.xml下查看, tomcat7+中JS的mime定义如下:

<mime-mapping>
     <extension>js</extension>
     <mime-type>application/javascript</mime-type>
</mime-mapping>

检测GZIP压缩效果

启用了TOMCAT这个压缩功能后,我们如何来测试压缩是否有效呢?

首先Tomcat是根据浏览器请求头中的accept-encoding来判断浏览器是否支持压缩功能,如果这个值包含有gzip,就表明浏览器支持gzip压缩内容的浏览,我们可以用两种方法来验证压缩是否生效。

测试方法一:通过浏览器直接请求

大家直接通过浏览器访问启用了压缩配置的服务器,然后通过抓包工具查看抓到的数据包,或者通过比如chrome浏览器的开发者工具查看network项。

console-net-2.png!

上图是我的首页的检测结果,和之前比起来明显要小很多,浏览器速度也更快。

console-net-1.png

这张图是未为tomcat开启gzip压缩的检测结果,大家可能发现一个问题,就是好像有的文件被压缩了,有的比如jquery的文件并未被压缩。

问题分析

究竟是怎么回事呢,搜索了一下,找到这个解释:

Note: There is a tradeoff between using compression (saving your bandwidth) and using the sendfile feature (saving your CPU cycles). If the connector supports the sendfile feature, e.g. the NIO connector, using sendfile will take precedence over compression. The symptoms will be that static files greater that 48 Kb will be sent uncompressed. You can turn off sendfile by setting useSendfile attribute of the connector, as documented below, or change the sendfile usage threshold in the configuration of the DefaultServlet in the default conf/web.xml or in the web.xml of your web application.

大致的意思就是对于大于48Kb的文件,为了节省cpu就不压缩而采用别的处理方法了(简单的思考一下就知道,服务器压缩文件一定是要消耗CPU的)。添加useSendfile="false"后,就可以被正常压缩了。

但是,优化这种事情,本身就是要做取舍的,本人非常不建议为了压缩几个大文件关闭sendfile配置。具体的原因请参考这篇文章:高性能Tomcat配置中sendFile选项带来的体验

测试方法二:使用站长工具

站长工具有一个gzip检测工具,网址为:http://tool.chinaz.com/Gzips/

我的首页检测结果如下图所示:

gzip-test-001.png

这里大家可以看到效果,压缩后,首页整整减少了三分之二的大小!

测试方法三:终极大招之写代码,利用httpclient工具测试

原理很简单,就是使用apache HttpClient访问该tomcat加载项目中的一个静态资源(比如一个js文件),然后打印请求的资源内容或资源ContentLength,如果打印的资源内容为乱码或ContentLength为-1,则说明gzip生效了。

public static void main(String[] args)
{
  String uri = "http://www.liuqianfei.com/resources/js/common/commons.js";
  HttpClient httpClient = new DefaultHttpClient();
  HttpGet get = new HttpGet(uri);
  ResponseHandler<String> responseHandler = new BasicResponseHandler();

  try {
    // 设置模拟头部
    get.setHeader("Accept-Encoding", "gzip,deflate");
    get.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36");

    String content = httpClient.execute(get, responseHandler);
    System.out.println(content); // 如果gzip生效,这里会打印出乱码;否则会打印出jquery.js的内容

    /*
    HttpResponse response = httpClient.execute(get);
    long cLen = response.getEntity().getContentLength();
    System.out.println(cLen); // 如果gzip生效,这里打印的长度值将会是 -1 或一个比原始文件大小小很多的值
    */    

  } catch(Exception e) {
    // ignore ...
  } finally {
    httpClient.getConnectionManager().shutdown();    
  }

}

好了,对于Tomcat性能优化,开启GZIP压缩,并测试的体会就写到这了,如果你在使用tomcat作为服务器,不妨试一下本文中的方法,会有意想不到的惊喜!

如果觉得这对你有用,请随意赞赏,给与作者支持
评论 0
最新评论