Tomcat 配置gzip无效

提升Tomcat性能方法有很多种,使用NIO Connector和启用gzip压缩是其中两种。

NIO:Java New IO,使用了多路复用的技术,无疑要比普通的IO socket要高效。

gzip:对需要传输到前台的内容首先在内存中进行gzip压缩,这样可以大大的减少网络带宽占用。前提是前台的Accept-Encoding允许gzip。

但是,当同时配置了这两个时,会发现大于48KB的文件并没有进行压缩。

经查Tomcat源码,发现org.apache.catalina.servlets.DefaultServlet中:

/**
    * Check if sendfile can be used.
    */
    protected boolean checkSendfile(HttpServletRequest request,
                                  HttpServletResponse response,
                                  CacheEntry entry,
                                  long length, Range range) {
        if ((sendfileSize > 0)
            && (entry.resource != null)
            && ((length > sendfileSize) || (entry.resource.getContent() == null))
            && (entry.attributes.getCanonicalPath() != null)
            && (Boolean.TRUE == request.getAttribute("org.apache.tomcat.sendfile.support"))
            && (request.getClass().getName().equals("org.apache.catalina.connector.RequestFacade"))
            && (response.getClass().getName().equals("org.apache.catalina.connector.ResponseFacade"))) {
            request.setAttribute("org.apache.tomcat.sendfile.filename", entry.attributes.getCanonicalPath());
            if (range == null) {
                request.setAttribute("org.apache.tomcat.sendfile.start", new Long(0L));
                request.setAttribute("org.apache.tomcat.sendfile.end", new Long(length));
            } else {
                request.setAttribute("org.apache.tomcat.sendfile.start", new Long(range.start));
                request.setAttribute("org.apache.tomcat.sendfile.end", new Long(range.end + 1));
            }
            return true;
        } else {
            return false;
        }
    }

此处的sendfileSize = 48*1024,默认值为48KB,可以发现,当文件大小大于48KB时,Tomcat并未马上将内容写回到output中,而是把文件的路径记录下来。

/**
    * Serve the specified resource, optionally including the data content.
    *
    * @param request The servlet request we are processing
    * @param response The servlet response we are creating
    * @param content Should the content be included?
    *
    * @exception IOException if an input/output error occurs
    * @exception ServletException if a servlet-specified error occurs
    */
    protected void serveResource(HttpServletRequest request,
                                HttpServletResponse response,
                                boolean content)
        throws IOException, ServletException {

......

// Copy the input stream to our output stream (if requested)
            if (content) {
                try {
                    response.setBufferSize(output);
                } catch (IllegalStateException e) {
                    // Silent catch
                }
                if (ostream != null) {
                    if (!checkSendfile(request, response, cacheEntry, contentLength, null))
                        copy(cacheEntry, renderResult, ostream);
                } else {
                    copy(cacheEntry, renderResult, writer);
                }
            }
     
      ......

}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/612374a383998d5203e6f2746e717f96.html