閱讀152 返回首頁    go 技術社區[雲棲]


《HttpClient官方文檔》第六章 HTTP 緩存

第六章. HTTP緩存

6.1. 通用概念

HttpClient Cache 提供了用HttpClient(等效瀏覽器緩存的Java實現)來兼容HTTP / 1.1的緩存層。實現遵循責任鏈模式,HttpClient緩存的實現類可以替代默認無緩存的HttpClient;完全可以通過緩存實現的請求將不會觸發實際的原始請求。在可以的情況下,使用GETs條件If-Modified-Since和/or If-None-Match請求頭,會自動驗證舊的緩存項。HTTP / 1.1緩存一般被設計成語義透明的,也就是說,緩存不會改變客戶端和服務器端的請求響應之間交換的意義。因此,向一個現有的客戶端-服務器的關係中添加HttpClient是安全的。盡管從一個HTTP協議的角度來看,緩存模塊是客戶端的一部分,實現的目標是滿足基於透明緩存代理的要求。最後,緩存HttpClient包括支持RFC 5861(stale-if-error和stale-while-revalidate)指定的cache – control擴展。 當緩存HttpClient執行一個請求時,它會通過以下流程:

  • 檢查要求是否符合基本的HTTP 1.1協議並嚐試正確的請求。
  • 刷新當前請求導致無效的一些緩存項。
  • 確定當前請求可以從緩存中提供。如果不能, 則直接將這個請求發送給原始服務器並換回響應,如果合適的話保存緩存.
  • 如果是cache-servable請求時,將嚐試從緩存中讀取。當緩存中沒有的情況下,調用原始的服務器,如果可以的話將響應緩存。
  • 如果緩存中的響應能夠被當做一個響應提供服務,構造一個包含ByteArrayEntity的BasicHttpResponse並返回。否則,嚐試重新驗證對原始服務器的緩存項.
  • 當一個緩存的響應不能重新生效的情況下,調用原始服務器,如果可以的話緩存響應.

當緩存HttpClient收到響應時,它通過以下流程:

  • 根據協議內容,檢查響應。
  • 確定響應是否可以被緩存。
  • 如果可以被緩存,讀取配置中允許的最多內容,並將其保存在緩存中。
  • 如果對緩存來說響應過大,則重新構建被消費的部分響應,並跳過緩存流程直接返回。

需要著重注意的是,HttpClient Cache本身並不是一個HttpClient的不同實現,而是通過插件的方式作為一個額外管道執行請求。

6.2. RFC-2616 規範

我們相信HttpClient緩存是無條件地符合RFC-2616。也就是說無論規範表明對於HTTP緩存 必須、不必須、可以、不可以,緩存層都會試圖以滿足這些條件的方式實現。 這就意味著,當你使用緩存模塊時,不會發生錯誤的行為。

6.3. Example Usage

下麵是一個如何建立一個基本的緩存HttpClient例子。根據配置,他會存儲一個最大數量為1000的緩存實例,每個最多能夠保存8192 bytes。這裏的數字僅僅是個例子,並不是規定,也不能被看做成建議。

CacheConfig cacheConfig = CacheConfig.custom()
    .setMaxCacheEntries(1000)
    .setMaxObjectSize(8192)
    .build();
RequestConfig requestConfig = RequestConfig.custom()
    .setConnectTimeout(30000)
    .setSocketTimeout(30000)
    .build();
CloseableHttpClient cachingClient = CachingHttpClients.custom()
    .setCacheConfig(cacheConfig)
    .setDefaultRequestConfig(requestConfig)
    .build();

HttpCacheContext context = HttpCacheContext.create();
HttpGet httpget = new HttpGet("https://www.mydomain.com/content/");
CloseableHttpResponse response = cachingClient.execute(httpget, context);
try {
    CacheResponseStatus responseStatus = context.getCacheResponseStatus();
    switch (responseStatus) {
        case CACHE_HIT:
            System.out.println("A response was generated from the cache with " +
                "no requests sent upstream");
            break;
        case CACHE_MODULE_RESPONSE:
            System.out.println("The response was generated directly by the " +
                "caching module");
            break;
        case CACHE_MISS:
            System.out.println("The response came from an upstream server");
            break;
        case VALIDATED:
            System.out.println("The response was generated from the cache " +
                "after validating the entry with the origin server");
            break;
    }
} finally {
    response.close();
}

6.4. 配置

HttpClient Cache 繼承了所有非緩存實現的配置項和參數(包括像超時時間、連接池大小這樣的設置選項)。對於緩存的具體配置,可以根據以下幾個方提供一個緩存配置實例指定行為:

緩存大小,後端存儲支持這些限製,可以像最大的可緩存響應體大小一樣指定緩存項的數量.

公共/私有緩存. 在默認情況下,緩存模塊本身是一個共享緩存,例如,不會緩存帶有授權請求頭的響應和標記為”Cache-Control: private”的響應。然而,如果緩存僅僅被應用於一個“用戶”(類似於瀏覽器緩存的行為)邏輯,那麼它將關閉共享緩存設置。

啟發式緩存. 按照RFC2616, 緩存可以緩存特定的緩存條目,即使沒有顯示原始設置的緩存控製頭。這種行為在默認情況下是關閉的,但是如果你處理的是一個沒有完全設置原始請求頭的請求,你可能想要打開它。你需要一個可以啟發式的緩存,然後指定一個默認的新生命周期,並且/或者資源被最後修改後的一小段時間。參考HTTP/1.1 RFC的13.2.2和13.2.4部分,可以獲得啟發式緩存的更多細節。

後台驗證. 緩存模塊支持RFC5861的stale-while-revalidate指令,允許後台特定的緩存項重新生效。可以需要調整設置後台工作線程的最小和最大工作數量,以及他們回收前閑置的最大時間。沒有足夠的worker來跟上需求時,您還可以控製隊列的大小用於重新生效線程。

6.5. 後端存儲

默認的HttpClient Cache的實現會存儲緩存項,並且在應用的JVM內存中緩存響應體。雖然這些能夠提供高性能,但是有內存大小的限製,或者因為緩存項在應用重啟後會失效,所以可能並不適用於您的應用。當前版本允許將緩存項保存到硬盤上,或者使用其他外部進程EhCache和Memcached存儲緩存項。如果這些選項滿足不了你的應用,可以通過實現HttpCachedStorage提供你自己的後台存儲,並且在構建的時候提供給緩存HttpClient。在這種情況下,緩存項會通過你自己的框架存儲,但是會重用所有HTTP/1.1協議的邏輯和緩存處理。一般來說,應該能夠創建一個支持原子操作的key/value存儲(類似於java的Map接口)的HttpCachedStorage實現。最後,通過一些額外的努力完全有可能建立一個多層緩存層次結構; 比如,包裝一個內存中的緩存HttpClient在磁盤上的存儲緩存條目,在memcached中遠程存儲,後一種模式類似於虛擬內存,L1 / L2處理器緩存等。

轉載自 並發編程網 - ifeve.com

最後更新:2017-05-19 12:05:15

  上一篇:go  帶著問題學 Spring MVC 源碼: 一、概述
  下一篇:go  《雲數據管理:挑戰與機遇》2.1 向量時鍾