HTTPClient4.5.2学习笔记(六):HTTP 缓存

来源:互联网 发布:安卓锁机软件制作教程 编辑:程序博客网 时间:2024/06/08 17:50

6.1. 基本概念

HttpClient Cache 是基于 HTTP/1.1,相当于浏览器缓存.其实现使用了责任链设计模式 , HttpClient 的缓存实现 可以为默认的非缓存HttpClient实现提供替代; 并且在完全满足缓存需求的同时不会影响实际的原始请求。 在有条件的Get请求、请求头部有If-Modified-Since 和 If-None-Match参数,则过期的缓存entity会被自动的与验证entity的实效性。

HTTP / 1.1缓存一般设计为语义透明;也就是说,缓存不应该改变客户端和服务器之间的请求 - 响应交换的含义。因此,将HttpClient缓存到现有的兼容客户端 - 服务器关系中应该是安全的。虽然缓存模块是从HTTP协议的角度来看的客户端的一部分,但实现的目标是与透明缓存代理的要求兼容。

最后,缓存HttpClient包括支持由RFC 5861指定的Cache-Control扩展(stale-if-error和stale-while-revalidate)。

当缓存HttpClient执行请求时,它将通过以下流程:

  1. 检查基本符合HTTP 1.1协议的请求,并尝试更正请求

  2. 刷新任何将被该请求无效的缓存条目。

  3. Determine if the current request would be servable from cache. If not, directly pass through the request to the origin server and return the response, after caching it if appropriate.确定当前请求是否可以从缓存中执行。如果没有,直接通过请求到源服务器并返回响应,然后如果需要缓存该请求资源。

  4. 如果它是一个可缓存可执行的请求,它将尝试从缓存中读取它。 如果不在缓存中,请调用源服务器并缓存响应(如果适用)。

  5. 如果缓存响应适合作为响应,则构造一个包含ByteArrayEntity的BasicHttpResponse并返回它。否则,尝试根据原始服务器重新验证缓存条目。

  6. 在无法重新验证的缓存响应的情况下,如果适用,请调用源服务器并缓存响应。

当缓存HttpClient收到响应时,它将通过以下流程:

  1. 检查符合协议的响应报文

  2. 决定是否响应报文是否能缓存

  3. 如果可以缓存,则尝试在配置允许的最大size下保存到缓存中.

  4. 如果响应报文对于缓存太大,而只能缓存响应报文的一部分则就进行直接的返回,不进行缓存操作。

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

6.2. 符合RFC-2616 规范

我们认为HttpClient Cache无条件地符合RFC-2616。也就是说,对于HTTP高速缓存无论规范MUST, MUST NOT, SHOULD, or SHOULD NOT,缓存层将会尝试以满足这些要求的方式进行操作。这意味着缓存模块在放入时不会产生不正确的行为。

6.3. 使用案例

 这是一个设置基本缓存HttpClient的简单例子,  根据配置,它将最多存储1000个缓存对象,每个对象的最大主体大小为8192个字节。这里选择的数字仅作为示例,并不是作为建议。

 CacheConfig cacheConfig=CacheConfig.custom()                      .setMaxCacheEntries(1000)                      .setMaxObjectSize(8192)                      .build();     RequestConfig requestConfig=RequestConfig.custom()                      .setConnectTimeout(1000)                      .setSocketTimeout(1000)                      .build();     CloseableHttpClient client=CachingHttpClients.custom()                      .setCacheConfig(cacheConfig)                      .setDefaultRequestConfig(requestConfig)                      .build();     HttpCacheContext context=HttpCacheContext.create();     HttpGet get=new HttpGet("http://www.baidu.com");     CloseableHttpResponse response=client.execute(get, 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”标记的Authorization标头或响应来缓存对请求的响应。但是,如果缓存仅由一个逻辑“用户”使用(与浏览器缓存类似),那么您将要关闭共享缓存设置。

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实现,并具有应用原子更新的能力。

最后,通过一些额外的努力,完全可以设置多层缓存层次结构; 例如,按照类似于虚拟内存,L1 / L2处理器缓存等的模式,将内存缓存HttpClient包装在围绕磁盘上存储高速缓存条目或在memcached中远程存储的缓存中。


0 0
原创粉丝点击