欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用ETags減少Web應(yīng)用帶寬和負(fù)載第1/2頁

 更新時間:2008年01月10日 19:09:38   作者:  
使用ETags減少Web應(yīng)用帶寬和負(fù)載

介紹

最近,大眾對于REST風(fēng)格應(yīng)用架構(gòu)表現(xiàn)出強(qiáng)烈興趣,這表明Web的優(yōu)雅設(shè)計開始受到人們的注意。現(xiàn)在,我們逐漸理解了“3W架構(gòu)(Architecture of the World Wide Web)”內(nèi)在所蘊(yùn)含的可伸縮性和彈性,并進(jìn)一步探索運(yùn)用其范式的方法。本文中,我們將探究一個可被Web開發(fā)者利用的、鮮為人知的工具,不引人注意的“ETag響應(yīng)頭(ETag Response Header)”,以及如何將它集成進(jìn)基于Spring和Hibernate的動態(tài)Web應(yīng)用,以提升應(yīng)用程序性能和可伸縮性。

我們將要使用的Spring框架應(yīng)用是基于“寵物診所(petclinic)”的。下載文件中包含了關(guān)于如何增加必要的配置及源碼的說明,你可以自己嘗試。

什么是“ETag”?

HTTP協(xié)議規(guī)格說明定義ETag為“被請求變量的實(shí)體值” (參見 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html —— 章節(jié) 14.19)。 另一種說法是,ETag是一個可以與Web資源關(guān)聯(lián)的記號(token)。典型的Web資源可以一個Web頁,但也可能是JSON或XML文檔。服務(wù)器單獨(dú)負(fù)責(zé)判斷記號是什么及其含義,并在HTTP響應(yīng)頭中將其傳送到客戶端。

ETag如何幫助提升性能?

聰明的服務(wù)器開發(fā)者會把ETags和GET請求的“If-None-Match”頭一起使用,這樣可利用客戶端(例如瀏覽器)的緩存。因?yàn)榉?wù)器首先產(chǎn)生ETag,服務(wù)器可在稍后使用它來判斷頁面是否已經(jīng)被修改。本質(zhì)上,客戶端通過將該記號傳回服務(wù)器要求服務(wù)器驗(yàn)證其(客戶端)緩存。

其過程如下:

  1. 客戶端請求一個頁面(A)。
  2. 服務(wù)器返回頁面A,并在給A加上一個ETag。
  3. 客戶端展現(xiàn)該頁面,并將頁面連同ETag一起緩存。
  4. 客戶再次請求頁面A,并將上次請求時服務(wù)器返回的ETag一起傳遞給服務(wù)器。
  5. 服務(wù)器檢查該ETag,并判斷出該頁面自上次客戶端請求之后還未被修改,直接返回響應(yīng)304(未修改——Not Modified)和一個空的響應(yīng)體。

本文的其余部分將展示在基于Spring框架的Web應(yīng)用中利用ETag的兩種方法,該應(yīng)用使用Spring MVC。首先我們將使用Servlet 2.3 Filter,利用展現(xiàn)視圖(rendered view)的MD5校驗(yàn)和(checksum)以實(shí)現(xiàn)生成ETag的方法(一個“淺顯的”ETag實(shí)現(xiàn))。 第二種方法使用更為復(fù)雜的方法追蹤view中所使用的model,以確定ETag有效性(一個“深入的”ETag實(shí)現(xiàn))。盡管我們使用的是Spring MVC,但該技術(shù)可以應(yīng)用于任何MVC風(fēng)格的Web框架。

在我們繼續(xù)之前,強(qiáng)調(diào)一下這里所展現(xiàn)的是提升動態(tài)產(chǎn)生頁面性能的技術(shù)。已有的優(yōu)化技術(shù)也應(yīng)作為整體優(yōu)化和應(yīng)用性能特性調(diào)整分析的一部分來考慮。(見下)。

自頂向下的Web緩存

本文主要涉及對動態(tài)生成頁面使用HTTP緩存技術(shù)。當(dāng)考慮提升Web應(yīng)用的性能的時候,應(yīng)采取一個整體的、自頂向下的方法。為了這一目的,理解HTTP請求經(jīng)過的各層是很重要的,應(yīng)用哪些適當(dāng)?shù)募夹g(shù)取決于你所關(guān)注的熱點(diǎn)。例如:

  • 將Apache作為Servlet容器的前端,來處理如圖片和javascript腳本這樣的靜態(tài)文件,而且還可以使用FileETag指令創(chuàng)建ETag響應(yīng)頭。
  • 使用針對javascript文件的優(yōu)化技術(shù),如將多個文件合并到一個文件中以及壓縮空格。
  • 利用GZip和緩存控制頭(Cache-Control headers)。
  • 為確定你的Spring框架應(yīng)用的痛處所在,可以考慮使用 JamonPerformanceMonitorInterceptor。
  • 確信你充分利用ORM工具的緩存機(jī)制,因此對象不需要從數(shù)據(jù)庫中頻繁的再生?;〞r間確定如何讓查詢緩存為你工作是值得的。
  • 確保你最小化數(shù)據(jù)庫中獲取的數(shù)據(jù)量,尤其是大的列表。如果每個頁面只請求大列表的一個小子集,那么大列表的數(shù)據(jù)應(yīng)由其中某個頁面一次獲得。
  • 使放入到HTTP session中的數(shù)據(jù)量最小。這樣內(nèi)存得到釋放,而且當(dāng)將應(yīng)用集群的時候也會有所幫助。
  • 使用數(shù)據(jù)庫明細(xì)(database profiling)工具來查看在查詢的時候使用了什么索引,在更新的時候整個表沒有被上鎖。

當(dāng)然,應(yīng)用性能優(yōu)化的至理名言是:兩次測量,一次剪裁(measure twice, cut once)。哦,等等,這是對木工而言的!沒錯,但是它在這里也很適用!

ETag Filter內(nèi)容體

我們要考慮的第一種方法是創(chuàng)建一個Servlet Filter,它將基于頁面(MVC中的“View”)的內(nèi)容產(chǎn)生其ETag 記號。乍一看,使用這種方法所獲得的任何性能提升看起來都是違反直覺的。我們?nèi)匀徊坏貌划a(chǎn)生頁面,而且還增加了產(chǎn)生記號的計算時間。然而,這里的想法是減少帶寬使用。在大的響應(yīng)時間情形下,如你的主機(jī)和客戶端分布在這個星球的兩端,這很大程度上是有益的。我曾見過東京辦公室使用紐約服務(wù)器上托管的應(yīng)用,其響應(yīng)時間達(dá)到了 350 ms。隨著并發(fā)用戶數(shù)的增長,這將變成巨大的瓶頸。

代碼

我們用來產(chǎn)生記號的技術(shù)是基于從頁面內(nèi)容計算MD5哈希值。這通過在響應(yīng)之上創(chuàng)建一個包裝器來實(shí)現(xiàn)。該包裝器使用字節(jié)數(shù)組來保存所產(chǎn)生的內(nèi)容,在filter鏈處理完成之后我們利用數(shù)組的MD5哈希值計算記號。

doFilter方法的實(shí)現(xiàn)如下所示。
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) req;
HttpServletResponse servletResponse = (HttpServletResponse) res;

  ByteArrayOutputStream baos = new ByteArrayOutputStream();
ETagResponseWrapper wrappedResponse = new ETagResponseWrapper(servletResponse, baos);
chain.doFilter(servletRequest, wrappedResponse);

  byte[] bytes = baos.toByteArray();

  String token = '"' + ETagComputeUtils.getMd5Digest(bytes) + '"';
servletResponse.setHeader("ETag", token); // always store the ETag in the header

  String previousToken = servletRequest.getHeader("If-None-Match");
if (previousToken != null && previousToken.equals(token)) { // compare previous token with current one
logger.debug("ETag match: returning 304 Not Modified");
servletResponse.sendError(HttpServletResponse.SC_NOT_MODIFIED);
// use the same date we sent when we created the ETag the first time through
servletResponse.setHeader("Last-Modified", servletRequest.getHeader("If-Modified-Since"));
} else  { // first time through - set last modified time to now
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MILLISECOND, 0);
Date lastModified = cal.getTime();
servletResponse.setDateHeader("Last-Modified", lastModified.getTime());

  logger.debug("Writing body content");
servletResponse.setContentLength(bytes.length);
ServletOutputStream sos = servletResponse.getOutputStream();
sos.write(bytes);
sos.flush();
sos.close();
}
}

相關(guān)文章

  • PHP加密解密實(shí)例分析

    PHP加密解密實(shí)例分析

    這篇文章主要介紹了PHP加密解密實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了PHP自定義函數(shù)實(shí)現(xiàn)字符串加密與對應(yīng)解密的相關(guān)技巧,需要的朋友可以參考下
    2015-12-12
  • PHP實(shí)現(xiàn)刪除多重數(shù)組對象屬性并重新賦值的方法

    PHP實(shí)現(xiàn)刪除多重數(shù)組對象屬性并重新賦值的方法

    這篇文章主要介紹了PHP實(shí)現(xiàn)刪除多重數(shù)組對象屬性并重新賦值的方法,涉及php結(jié)合sphinx操作數(shù)組元素的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-06-06
  • php使用json-schema模塊實(shí)現(xiàn)json校驗(yàn)示例

    php使用json-schema模塊實(shí)現(xiàn)json校驗(yàn)示例

    這篇文章主要介紹了php使用json-schema模塊實(shí)現(xiàn)json校驗(yàn),結(jié)合實(shí)例形式分析了json-schema模塊的安裝及使用json-schema模塊進(jìn)行json校驗(yàn)的相關(guān)操作技巧,需要的朋友可以參考下
    2019-09-09
  • php join函數(shù)應(yīng)用

    php join函數(shù)應(yīng)用

    php join函數(shù)應(yīng)用,需要的朋友可以參考下。
    2011-05-05
  • php實(shí)現(xiàn)的返回數(shù)據(jù)格式化類實(shí)例

    php實(shí)現(xiàn)的返回數(shù)據(jù)格式化類實(shí)例

    這篇文章主要介紹了php實(shí)現(xiàn)的返回數(shù)據(jù)格式化類及其應(yīng)用實(shí)例,包括針對XML、JSON等的格式化,非常具有實(shí)用價值,需要的朋友可以參考下
    2014-09-09
  • PHP 文件寫入和讀取操作實(shí)例詳解【必看篇】

    PHP 文件寫入和讀取操作實(shí)例詳解【必看篇】

    這篇文章主要介紹了PHP 文件寫入和讀取操作,結(jié)合實(shí)例形式詳細(xì)分析了PHP針對文件的打開、讀取、寫入及指針操作相關(guān)使用技巧,需要的朋友可以參考下
    2019-11-11
  • mysql5的sql文件導(dǎo)入到mysql4的方法

    mysql5的sql文件導(dǎo)入到mysql4的方法

    有時候用到將高版本的數(shù)據(jù)庫轉(zhuǎn)移到低版本的數(shù)據(jù)庫中,下面是mysql5數(shù)據(jù)轉(zhuǎn)到mysql4的方法
    2008-10-10
  • PHP面向?qū)ο蠛兔嫦蜻^程的區(qū)別詳解

    PHP面向?qū)ο蠛兔嫦蜻^程的區(qū)別詳解

    這篇文章主要給大家介紹了PHP面向?qū)ο蠛兔嫦蜻^程的區(qū)別,面向過程編程是將代碼組織為一系列函數(shù)或過程,面向?qū)ο缶幊淌菍⒋a組織為對象,其中包含屬性和方法,還有不懂的朋友可以參考閱讀本文
    2023-11-11
  • PHP面向?qū)ο缶偨Y(jié)

    PHP面向?qū)ο缶偨Y(jié)

    這篇文章主要介紹了PHP面向?qū)ο缶?較為詳細(xì)的介紹了PHP面向?qū)ο蟪绦蛟O(shè)計中的各種概念與常見技巧,非常具有實(shí)用價值,需要的朋友可以參考下
    2014-11-11
  • php英文單詞統(tǒng)計器

    php英文單詞統(tǒng)計器

    這篇文章主要為大家詳細(xì)介紹了php英文單詞統(tǒng)計器的實(shí)現(xiàn)代碼,
    2016-06-06

最新評論