当网站从服器端请求的数据较大时,在有限的带宽下就会造成浏览器加载缓慢,有时候会造成页面没有响应,使用户体验变得很差,tomcat为我们提供了有效的解决了办法,就是使用压缩来解决传输问题。
tomcat使用HTTP/1.1 GZIP 来压缩,以减少带宽压力,
首先介绍下gzip:
HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度。这一般是指WWW服务器中安装的一个功能,当有人来访问这个服务器中的网站时,服务器中的这个功能就将网页内容压缩后传输到来访的电脑浏览器中显示出来.一般对纯文本内容可压缩到原大小的40%.这样传输就快了,效果就是你点击网址后会很快的显示出来.当然这也会增加服务器的负载. 一般服务器中都安装有这个功能模块的.
我们使用简单的例子来介绍tomcat的压缩使用:(使用firebug查看请求情况)
首先是一个简单的servlet:
内容:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out
.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
out.println(" <BODY>");
out.print(" <select> ");
for (int i = 0; i < 100000; i++) {
out.print("<option>testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest"+i+"</option>");
}
out.println("</select>");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
我们将输出一个十万个选项的下拉框,在不使用的压缩的时候:
请求数据达到9m ,大概的计算下我的下载用时(4m长城宽带):9*1024/(4*1024/8)=18m ,加上多人共享带宽,也就是差不多20m。firebug显示20.96。
这个速度网站体验肯定是很差的,接下来使用tomcat的压缩以后看看:
当然是要对其进行配置:
有以下几个参数可以使用:
compression="on"
是否启用压缩 on为启用(文本数据压缩) off为不启用, force 压缩所有数据
compressionMinSize1="2048"
当超过最小数据大小才进行压缩
noCompressionUserAgents="gozilla, traviata"
哪些客户端发出的请求不压缩,默认是不限制
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"
配置想压缩的数据类型,默认是 text/html,text/xml,text/plain
配置以后是这样的:
<Connector port="8088" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
compression="on"
compressionMinSize1="2048"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"/>
启动后再看:
这次数据被压缩到274.7k,响应速度也减少了一半,当然,服务器的数据压缩和浏览器的数据解压都需要使用时间。
例子完毕,
当然tomcat的压缩技术还有很多其他的特性,然而对于大数据量的请求不光是要使用这种技术,还需要在其他地方下功夫,比如ajax技术,缓存等等,
也希望大家补充学习,谢谢。
配置tomcat的gzip压缩功能之后,配置有个compressionMinSize选项,表示压缩响应的最小值,只有当响应报文大小大于这个值的时候才会对报文进行压缩。但是有时候你会发现这个配置并不起作用,貌似只要客户端加了Accept-Encoding: gzip, deflate,响应就是压缩的,无论响应报文体有多大,这是怎么回事呢?
查看tomcat源码,关于压缩条件控制的地方:org.apache.coyote.http11.AbstractHttp11Processor类中:
| |
可以看到,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形式帮你返回消息,响应肯定是要被压缩的。
补充:当数据量小的时候,压缩后反而会导致数据量表大。
如果是Tomcat 6/7, (影响最新Tomcat 7.0.29)
需要在Connector里面加上:
useSendfile=”false”
否则大于大于48K的文件不会压缩。(Tomcat 的Bug)
参考:http://www.cnblogs.com/codewater/articles/2228594.html
http://zhaoyanblog.com/archives/652.html