《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("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 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

时间: 2024-10-03 21:14:36

《HttpClient官方文档》第六章 HTTP 缓存的相关文章

《HttpClient 官方文档》第五章 Fluent API

第五章:流式 API 5.1 易用 API 接口 4.2版本的 HttpClient 带来了一组非常容易使用的流式 API(Fluent API) 接口.暴露的流式API(Fluent API) 接口中仅仅是 HttpClient 最基本的一些功能,这些接口是在不需要使用 HttpClient 丰富的灵活性时,为了一些简单的功能而准备的. 例如:流式接口(Fluent API) 增加了使用者对连接的管理和资源的分配上的便利性.这里有一系列通过 HttpClient 流式接口(Fluent API

《HttpClient 官方文档》第三章 HTTP 状态管理

通常 HTTP 被设计为无状态,面向请求/响应的协议,对于有一些逻辑相关的请求/响应交换的有状态会话没有特别的规定.正当 HTTP 协议越来越流行和被认可,越来越多之前没有打算使用它的系统,现在也开始为了应用程序而使用它.例如电子商务应用的内容传输.因此,支持 HTTP 状态管理变得非常有必要. NetScape(网景公司),曾经引领网页客户端和服务器端软件的发展,在他们的产品中基于专有的规范,提供了 HTTP 状态管理的支持.之后,NetScape 尝试通过发布规范草案来标准化这种机制.这些努

《HttpClient官方文档》2.7 连接套接字工厂

2.7. Socket连接工厂 HTTP连接在内部使用java.net.Socket类的对象来处理数据在线路上的传输. 然而,他们依靠 ConnectionSocketFactory接口来创建,初始化和连接Socket.HttpClient的使用者能够在运行时,提供应用程序特定的Socket初始化代码.PlainConnectionSocketFactory类是创建和初始化普通(未加密)套接字的默认工厂类. 创建一个套接字和连接到主机的过程是解耦的,以便连接操作被阻塞的时候套接字能够被关闭 Ht

《HttpClient官方文档》4.8 SPNEGO/Kerberos验证

SPNEGO(简单并且受保护的GSSAPI协商机制)被设计为当两端都不知道他人可以提供,或使用什么时所提供的验证服务.它可以包装其他的机制,但是目前HttpClient4.2是按照Kerbros单独设计的. 4.8.1SPNEGO在HttpClient中的支持 SPNEGO验证方案被Sun Java 1.5以上版本兼容.1.6以上的Java版本被强烈推荐,因为它已经完全支持了SPNEGO验证. Sun JRE 提供了相关支持类来处理几乎所有的Kerb er和SPNEGO的令牌.这意味着很多步骤是

《HttpClient官方文档》1.3 HTTP执行上下文

1.3 HTTP执行上下文 HTTP起初是被设计成一种无状态的.面向请求和响应的协议.然而实际的应用经常需要在请求-响应切换过程中保存状态信息.为了使应用能够维持处理状态,HttpClient允许HTTP请求可以在一个特殊的上下文环境(HttpContext)中执行.如果一个context在连续的HTTP请求中被复用,那么这些逻辑相关的请求可以参与到同一个逻辑会话中.HttpContext功能与java.util.Map<String, Object>类似,它是一组任意值的集合.一个应用程序可

《HttpClient官方文档》HTTP验证4.4-4.7

4.4 HTTP验证和执行上下文 HttpClient依赖于AuthState类来追踪验证进程的状态的详细信息.HttpClient在执行HTTP请求执行时,创建AuthState的两个实例:一个对目标主机认证,另外一个用于代理认证.一旦目标主机或者代理要求用户验证,对应的AuthState实例将会在验证过程中被AuthScope,AuthScheme和Crednetials填充.这个AuthState可以被检查用于找出哪种类型要求验证,是否对应的AuthScheme被找到,以及凭证提供者可以找

《HttpClient官方文档》1.2 HttpClient 接口

1.2. HttpClient 接口 HttpClient 接口表示最基本的HTTP请求执行要约.它不会对请求执行过程加上约束或一些特定的信息,并且保留连接管理,状态管理,认证和处理重定向的细节到各自的实现中.这会使它更方便的使用额外功能来装饰接口,如响应内容缓存. 通常来说, HttpClient接口的实现负责处理特定方面的HTTP协议,比如重定向.身份认证处理.对连接的持久性和维持连接存活长短的决策之类的多个处理程序和策略接口实现的门面. 这使得用户能够有选择性的将一些自定义的,基于特定应用

《HttpClient官方文档》2.3 HTTP连接管理

2.3. HTTP 连接管理 2.3.1. 管理连接和连接管理器 HTTP 连接是复杂的. 有状态的. 非线程安全的对象,因此需要恰当的管理才能正常工作.HTTP连接一次只能由一个线程使用.HttpClient使用实现了HttpClientConnectionManager接口,被称为HTTP连接管理器的特殊实体去访问HTTP连接. HTTP连接管理器的作用是作为一个工厂类来为新的HTTP连接使用,管理持久连接的生命周期和同步访问,确保一次只能由一个线程使用连接. HTTP连接管理器内部与Man

《HttpClient官方文档》1.1 执行请求(二)

1.1.4. HTTP 实体 HTTP 消息可以携带与其相关联的请求或响应的内容实体.实体可以在一些请求和响应中找到,因为它们也是可选的.使用了实体的请求被称为封闭实体请求.HTTP规范定义了两种封闭实体的方法: POST 和PUT.响应通常期望包含一个内容实体. 这个规则也有特例,就像HEAD 方法和 204 No Content,304 Not Modified, 205 Reset Content 响应. HttpClient根据其内容来源以此区分三种类型的实体: streamed(流式)