1. 程式人生 > >使用Cache-Control和gzip提升tomcat應用效能(整理)

使用Cache-Control和gzip提升tomcat應用效能(整理)

    這個其實應該是常識,只不過以前做的J2EE應用大部分是內網裡跑的東西,所以效能上沒什麼問題。這次APIS由於有在外面用的可能,加上使用了一些比較大的javascript框架(Ext),所以效能問題瞬間竄了上來。
以前做的J2EE應用沒有使用上達500K的框架,最多就是幾十K的Prototype,所以沒什麼問題。一個頁面一般也就幾十K最多了。但這次還在開發中的APIS,由於還在用debug版本的庫,所以單單Ext就膨脹到了一個多M,加上不知道是Struts還是Tomcat預設寫入Response的cache-control: no cache,在遠端用起來就很慢,一般一個頁面需要十多秒種甚至更久,實在無法忍受。前幾天集中解決了問題。
    首先是Cache-Control的問題,Google了好一陣,沒有什麼直接配置的方法,只好自己抄了一個一個Filter,通過和web.xml裡配置的配合勉強湊合著用。一般就是對*.do實施no-cache政策,其他需要快取的img, js檔案,統統加上長達兩週的快取期限。ETag實在不會用,就先用這個快取策略吧。

Filter的程式碼:

  1. publicclass ResponseHeaderFilter implements Filter {
  2.     FilterConfig fc; 
  3. publicvoid doFilter(ServletRequest req, ServletResponse res,
  4.             FilterChain chain) throws IOException, ServletException {
  5.         HttpServletResponse response = (HttpServletResponse) res;
  6. // set the provided HTTP response parameters
  7. for (Enumeration e = fc.getInitParameterNames(); e.hasMoreElements();) {
  8.             String headerName = (String) e.nextElement();
  9.             response.addHeader(headerName, fc.getInitParameter(headerName));
  10.         }
  11. // pass the request/response on
  12.         chain.doFilter(req, response);
  13.     } 
  14. publicvoid init(FilterConfig filterConfig) {
  15. this.fc = filterConfig;
  16.     } 
  17. publicvoid destroy() {
  18. this.fc = null;
  19.     } 
  20. }

web.xml裡的巧妙配置:

  1. <filter>
  2. <filter-name>NoCache</filter-name>
  3. <filter-class>apis.server.common.util.ResponseHeaderFilter</filter-class>
  4. <init-param>
  5. <param-name>Cache-Control</param-name>
  6. <param-value>no-cache, must-revalidate</param-value>
  7. </init-param>
  8. </filter>
  9. <filter>
  10. <filter-name>CacheForWeek</filter-name>
  11. <filter-class>apis.server.common.util.ResponseHeaderFilter</filter-class>
  12. <init-param>
  13. <param-name>Cache-Control</param-name>
  14. <param-value>max-age=604800, public</param-value>
  15. </init-param>
  16. </filter>
  17. <filter-mapping>
  18. <filter-name>NoCache</filter-name>
  19. <url-pattern>*.do</url-pattern>
  20. </filter-mapping>
  21. <filter-mapping>
  22. <filter-name>CacheForWeek</filter-name>
  23. <url-pattern>/images/*</url-pattern>
  24. </filter-mapping>
  25. <filter-mapping>
  26. <filter-name>CacheForWeek</filter-name>
  27. <url-pattern>/img/*</url-pattern>
  28. </filter-mapping>
  29. <filter-mapping>
  30. <filter-name>CacheForWeek</filter-name>
  31. <url-pattern>/icons/*</url-pattern>
  32. </filter-mapping>
  33. <filter-mapping>
  34. <filter-name>CacheForWeek</filter-name>
  35. <url-pattern>/ext/*</url-pattern>
  36. </filter-mapping>
  37. <filter-mapping>
  38. <filter-name>CacheForWeek</filter-name>
  39. <url-pattern>*.js</url-pattern>
  40. </filter-mapping>
  41. <filter-mapping>
  42. <filter-name>CacheForWeek</filter-name>
  43. <url-pattern>*.css</url-pattern>
  44. </filter-mapping>

   
    (插入一段:在探測這些效能問題的時候,我使用的是一個Firebug的外掛,也就是Firefox外掛的外掛-YSlow,好像是Yahoo的,結合Firebug裡XHR的Net這塊做Profiling,效果很不錯,很容易就知道瓶頸)

    還有一個gzip的辦法,就是在伺服器壓縮內容,再傳給瀏覽器。現在主流的瀏覽器都支援gzip壓縮,而且這些html和js文字壓縮起來很厲害,基本上可以有40%的壓縮率。辦法在servel.xml的註釋裡也有寫,就是在Connector元素里加上

            compression="on"
            compressionMinSize="2048"
            noCompressionUserAgents="gozilla,traviata"
            compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain"

以上的內容大部分都是Google得來,我自己做了一下整理