Apache HttpClient 4.5.x 学习总结十三:HTTP Caching(HTTP缓存)

第6章 HTTP缓存

6.1 基本概念
HttpClient缓存模块为HttpClient提供了符合HTTP/1.1标准的缓存层(相当于浏览器的缓存)。其实现采用责任链设计模式,缓存版HttpClient可直接替代默认的非缓存版本:能从缓存直接响应的请求不会访问源服务器。当缓存条目过期时,系统会自动通过条件GET请求(使用If-Modified-SinceIf-None-Match请求头)向源服务器验证有效性。

HTTP/1.1缓存设计遵循语义透明原则:缓存不应改变客户端与服务器间请求-响应的语义。因此将缓存版HttpClient接入现有客户端-服务器体系是安全的。虽然缓存模块属于客户端,但其实现兼容透明缓存代理的要求。

此外,该模块支持RFC 5861定义的Cache-Control扩展指令(stale-if-errorstale-while-revalidate)。

缓存请求执行流程:

  1. 检查请求是否符合HTTP 1.1协议并修正
  2. 清除该请求可能失效的缓存条目
  3. 若请求无法通过缓存响应,则直接访问源服务器(响应可能被缓存)
  4. 若请求可通过缓存响应:
    • 缓存存在:返回缓存响应(需验证时向源服务器重新验证)
    • 缓存不存在:访问源服务器并缓存响应

缓存响应接收流程:

  1. 检查响应是否符合协议规范
  2. 判断响应是否可缓存
  3. 若可缓存且未超过配置大小,则存入缓存
  4. 若响应过大则直接返回,不缓存

关键说明:缓存版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缓存设计

核心知识点总结:

  1. 缓存本质

    • 责任链模式实现的语义透明缓存层
    • 核心目标:减少源服务器请求,提升性能
  2. 工作流程

    • 请求阶段:优先检查缓存 → 无效则访问源服务器
    • 响应阶段:协议检查 → 缓存策略判断 → 存储控制
  3. 高级特性

    • 条件验证(If-Modified-Since等)
    • RFC 5861指令支持(stale-if-error
    • 启发式缓存(无缓存头时的智能处理)
  4. 配置要点

    • 容量限制(条目数/响应体大小)
    • 公共缓存 vs 私有缓存场景
    • 后台验证线程池调优
  5. 存储架构

    • 内存:默认方案,适合临时缓存
    • 磁盘/外部存储:持久化方案(EhCache/memcached)
    • 自定义接口:灵活适配键值存储系统

通俗易懂的解释:

HTTP缓存 ≈ 快递驿站

  1. 基础逻辑
  • 你下单(发送请求)时,驿站先检查是否有现成包裹(缓存命中)
  • 若无则向商家订货(访问源服务器),新包裹可能存驿站(缓存响应)
  • 取包裹时驿站检查是否过期(缓存验证),过期则联系商家确认(条件GET)
  1. 高级能力
  • 语义透明:驿站不会拆你的包裹(不改变数据内容)
  • 智能囤货:即使商家没说能囤(无缓存头),驿站按规则存常用品(启发式缓存)
  • 专属货架:私有缓存像VIP货架(如带密码的包裹单独存放)
  1. 存储方案
  • 小货架:内存存储 → 取货快但容量小(重启清空)
  • 大仓库:磁盘/memcached → 能存大件(文件),重启不丢
  • 自定义仓库:用自家仓库(实现接口),但遵守相同管理规则
  1. 性能秘籍
  • 后台验货:边让你取旧包裹(stale-while-revalidate),边后台检查新鲜度
  • 多级缓存:像驿站门口放畅销品(内存),后院存大件(磁盘)

典型场景

  • 频繁访问的API数据 → 内存缓存提速
  • 大型静态文件(图片/视频)→ EhCache磁盘存储
  • 分布式系统 → memcached统一缓存池
posted @ 2025-07-24 14:11  hqq的进阶日记  阅读(21)  评论(0)    收藏  举报