HttpClient 4.5教程学习与翻译——第6章:HTTP 缓存

原文链接

第6章:HTTP 缓存

6.1. 一般概念

HttpClient Cache提供了一个与HttpClient一起使用的HTTP / 1.1兼容缓存层 —— 相当于浏览器缓存的Java。实现遵循责任链(Chain of Responsibility)设计模式,其中缓存HttpClient实现可以为默认的非缓存HttpClient实现提供替代; 完全可以从缓存中满足的请求不会导致实际的原始请求。使用条件GET和If-Modified-Since和/或If-None-Match请求标头,尽可能使用原点自动验证过时的缓存条目。
HTTP / 1.1缓存通常设计为语义透明(semantically transparent); 也就是说,缓存不应该改变客户端和服务器之间的请求 - 响应交换的含义。因此,将缓存HttpClient放入现有的兼容客户端 - 服务器关系应该是安全的。虽然从HTTP协议的角度来看,缓存模块是客户端的一部分,但实现的目的是与透明缓存代理上的要求兼容。
最后,缓存HttpClient包括支持RFC 5861指定的Cache-Control扩展(stale-if-error和stale-while-revalidate)。

当缓存HttpClient执行请求时,它会经历以下流程:

  • 检查基本符合HTTP 1.1协议的请求,并尝试更正请求。
  • 刷新将被此请求无效的任何缓存条目。
  • 确定当前请求是否可以从缓存中获取。如果没有,直接将请求传递给原始服务器并在适当时缓存后返回响应。
  • 如果它是一个可缓存服务的请求,它将尝试从缓存中读取它。如果它不在缓存中,请调用原始服务器并缓存响应(如果适用)。

当缓存HttpClient收到响应时,它会经历以下流程:

  • 检查协议合规性的响应
  • 确定响应是否可缓存
  • 如果它是可缓存的,请尝试读取配置中允许的最大大小并将其存储在缓存中。
  • 如果响应对于缓存而言太大,则重新构建部分消耗的响应并直接返回它而不缓存它。

值得注意的是,缓存HttpClient本身并不是HttpClient的不同实现,但它通过将自身作为附加处理组件插入到请求执行管道中来工作。

6.2. RFC-2616合规性

我们相信HttpClient Cache无条件地符合RFC-2616。也就是说,无论 HTTP缓存规范指示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)
        .setSocketTimeout(30000)
        .build();
CloseableHttpClient cachingClient = CachingHttpClients.custom()
        .setCacheConfig(cacheConfig)
        .setDefaultRequestConfig(requestConfig)
        .build();

HttpCacheContext context = HttpCacheContext.create();
HttpGet httpget = new HttpGet("http://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继承了默认非缓存实现的所有配置选项和参数(这包括设置超时和连接池大小等选项)。对于特定于缓存的配置,您可以提供CacheConfig实例以自定义以下区域的行为:
缓存大小(Cache size). 如果后端存储支持这些限制,则可以指定最大缓存条目数以及最大可缓存响应主体大小。
公共/私人缓存(Public/private caching). 默认情况下,缓存模块将自身视为共享(公共)缓存,并且不会缓存对具有授权标头或标记为“Cache-Control:private”的响应的请求的响应。但是,如果缓存仅由一个逻辑“用户”使用(表现类似于浏览器缓存),那么您将需要关闭共享缓存设置。
启发式缓存(Heuristic caching).根据RFC2616,缓存可以缓存某些缓存条目,即使源没有设置显式缓存控制头。默认情况下,此行为处于关闭状态,但如果您正在使用未设置正确标头但仍希望缓存响应的原点,则可能需要启用此功能。您将需要启用启发式缓存,然后指定默认的新鲜度生命周期和/或自上次修改资源以来的一小部分时间。有关启发式缓存的更多详细信息,请参阅HTTP / 1.1 RFC的第13.2.2节和第13.2.4节。
背景验证(Background validation). 缓存模块支持RFC5861的stale-while-revalidate指令,该指令允许某些缓存条目重新验证在后台发生。您可能希望调整后台工作线程的最小和最大数量的设置,以及它们在回收之前可以空闲的最长时间。当没有足够的工作人员来满足需求时,您还可以控制用于重新验证的队列的大小。

6.5. 存储后台

缓存HttpClient的默认实现将缓存条目和缓存的响应主体存储在应用程序的JVM的内存中。虽然这提供了高性能,但由于大小限制或缓存条目是短暂的并且在应用程序重新启动后无法生存,因此它可能不适合您的应用程序。当前版本包括支持使用EhCache和memcached实现存储缓存条目,这些实现允许将缓存条目溢出到磁盘或将它们存储在外部进程中。
如果这些选项都不适合您的应用程序,则可以通过实现HttpCacheStorage接口然后在构建时将其提供给缓存HttpClient来提供您自己的存储后台。在这种情况下,将使用您的方案存储缓存条目,但您将重用所有围绕HTTP / 1.1合规性和缓存处理的逻辑。一般来说,应该可以使用能够应用原子更新的任何支持键/值存储(类似于Java Map接口)的东西创建HttpCacheStorage实现。
最后,通过一些额外的努力,完全可以建立一个多层缓存层次结构。例如,将内存缓存HttpClient包装在一个存储缓存条目的磁盘上或远程存储在memcached中,遵循类似于虚拟内存,L1 / L2处理器缓存等的模式。
上一章: 流畅的API
下一章: 高级

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342