Apache HttpClient 4.5.x 學習總結十三:HTTP Caching(HTTP緩存)
第6章 HTTP緩存
6.1 基本概念
HttpClient緩存模塊為HttpClient提供了符合HTTP/1.1標準的緩存層(相當于瀏覽器的緩存)。其實現采用責任鏈設計模式,緩存版HttpClient可直接替代默認的非緩存版本:能從緩存直接響應的請求不會訪問源服務器。當緩存條目過期時,系統會自動通過條件GET請求(使用If-Modified-Since和If-None-Match請求頭)向源服務器驗證有效性。
HTTP/1.1緩存設計遵循語義透明原則:緩存不應改變客戶端與服務器間請求-響應的語義。因此將緩存版HttpClient接入現有客戶端-服務器體系是安全的。雖然緩存模塊屬于客戶端,但其實現兼容透明緩存代理的要求。
此外,該模塊支持RFC 5861定義的Cache-Control擴展指令(stale-if-error和stale-while-revalidate)。
緩存請求執行流程:
- 檢查請求是否符合HTTP 1.1協議并修正
- 清除該請求可能失效的緩存條目
- 若請求無法通過緩存響應,則直接訪問源服務器(響應可能被緩存)
- 若請求可通過緩存響應:
- 緩存存在:返回緩存響應(需驗證時向源服務器重新驗證)
- 緩存不存在:訪問源服務器并緩存響應
緩存響應接收流程:
- 檢查響應是否符合協議規范
- 判斷響應是否可緩存
- 若可緩存且未超過配置大小,則存入緩存
- 若響應過大則直接返回,不緩存
關鍵說明:緩存版HttpClient并非獨立實現,而是作為請求執行管道的附加處理組件。
6.2 RFC-2616合規性
HttpClient緩存層完全符合RFC-2616規范,嚴格遵循協議中關于MUST/MUST NOT/SHOULD/SHOULD NOT的要求,確保行為正確性。
6.3 使用示例
以下配置創建基礎緩存HttpClient:
- 最多緩存1000個對象
- 單個響應體最大8192字節
注:示例數值僅作演示,非生產建議
// 緩存配置
CacheConfig cacheConfig = CacheConfig.custom()
.setMaxCacheEntries(1000) // 最大緩存條目
.setMaxObjectSize(8192) // 單個對象最大字節數
.build();
// 請求配置
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(30000) // 連接超時30秒
.setSocketTimeout(30000) // 數據傳輸超時30秒
.build();
// 創建緩存客戶端
CloseableHttpClient cachingClient = CachingHttpClients.custom()
.setCacheConfig(cacheConfig)
.setDefaultRequestConfig(requestConfig)
.build();
// 執行請求并檢查緩存狀態
HttpCacheContext context = HttpCacheContext.create();
HttpGet httpget = new HttpGet("http://www.mydomain.com/content/");
try (CloseableHttpResponse response = cachingClient.execute(httpget, context)) {
switch (context.getCacheResponseStatus()) {
case CACHE_HIT: // 緩存直接命中(未訪問源服務器)
case CACHE_MODULE_RESPONSE: // 緩存模塊直接生成響應
case CACHE_MISS: // 來自源服務器的新響應
case VALIDATED: // 緩存經源服務器驗證后使用
}
}
6.4 配置選項
緩存HttpClient繼承所有非緩存版的配置(如超時、連接池),并通過CacheConfig定制緩存行為:
| 配置項 | 作用 |
|---|---|
| 緩存大小 | 限制最大緩存條目數和響應體大小(需后端存儲支持) |
| 公共/私有緩存 | 默認公共緩存(不緩存帶Authorization頭或Cache-Control: private的響應),單用戶使用時需關閉 |
| 啟發式緩存 | 當源服務器未設置緩存頭時,按規則自動緩存(默認關閉) |
| 后臺驗證 | 支持RFC5861的stale-while-revalidate指令,可配置后臺驗證線程參數 |
6.5 存儲后端
- 默認內存存儲:高性能但受JVM內存限制,重啟后緩存丟失
- 擴展方案:
EhCache:支持磁盤持久化memcached:外部進程存儲
- 自定義存儲:實現
HttpCacheStorage接口,復用HTTP合規邏輯 - 多級緩存:可構建分層緩存(如內存+磁盤),類似CPU的L1/L2緩存設計
核心知識點總結:
-
緩存本質
- 責任鏈模式實現的語義透明緩存層
- 核心目標:減少源服務器請求,提升性能
-
工作流程
- 請求階段:優先檢查緩存 → 無效則訪問源服務器
- 響應階段:協議檢查 → 緩存策略判斷 → 存儲控制
-
高級特性
- 條件驗證(
If-Modified-Since等) - RFC 5861指令支持(
stale-if-error) - 啟發式緩存(無緩存頭時的智能處理)
- 條件驗證(
-
配置要點
- 容量限制(條目數/響應體大小)
- 公共緩存 vs 私有緩存場景
- 后臺驗證線程池調優
-
存儲架構
- 內存:默認方案,適合臨時緩存
- 磁盤/外部存儲:持久化方案(EhCache/memcached)
- 自定義接口:靈活適配鍵值存儲系統
通俗易懂的解釋:
HTTP緩存 ≈ 快遞驛站
- 基礎邏輯
- 你下單(發送請求)時,驛站先檢查是否有現成包裹(緩存命中)
- 若無則向商家訂貨(訪問源服務器),新包裹可能存驛站(緩存響應)
- 取包裹時驛站檢查是否過期(緩存驗證),過期則聯系商家確認(條件GET)
- 高級能力
- 語義透明:驛站不會拆你的包裹(不改變數據內容)
- 智能囤貨:即使商家沒說能囤(無緩存頭),驛站按規則存常用品(啟發式緩存)
- 專屬貨架:私有緩存像VIP貨架(如帶密碼的包裹單獨存放)
- 存儲方案
- 小貨架:內存存儲 → 取貨快但容量小(重啟清空)
- 大倉庫:磁盤/memcached → 能存大件(文件),重啟不丟
- 自定義倉庫:用自家倉庫(實現接口),但遵守相同管理規則
- 性能秘籍
- 后臺驗貨:邊讓你取舊包裹(
stale-while-revalidate),邊后臺檢查新鮮度- 多級緩存:像驛站門口放暢銷品(內存),后院存大件(磁盤)
典型場景:
- 頻繁訪問的API數據 → 內存緩存提速
- 大型靜態文件(圖片/視頻)→ EhCache磁盤存儲
- 分布式系統 → memcached統一緩存池
浙公網安備 33010602011771號