Http实战之缓存、重定向(2)

简介: Http实战之缓存、重定向(2)

缓存控制


关于缓存控制我们可以分为两部分讨论


1.服务端如何进行缓存控制

2.客户端如何进行缓存控制


服务端控制


服务端进行缓存控制主要依赖Cache-Control、及Expires请求头,其中Expires已经不推荐使用。其优先级如下所示:


  • 附加一个Cache-Control: no-store首部到响应中去;
  • 附加一个 Cache-Control: no-cache 首部到响应中去;
  • 附加一个 Cache-Control: must-revalidate 首部到响应中去;
  • 附加一个 Cache-Control: max-age 首部到响应中去;
  • 附加一个 Expires 日期首部到响应中去;


Cache-Control: no-store,客户端禁止使用缓存

Cache-Control: no-cache,客户端可以进行缓存,但每次使用缓存时必须跟服务器进行再验证

Cache-Control: must-revalidate ,客户端可以进行缓存,在缓存过期后必须进行再验证,跟no-cache的区别在于must-revalidate强调的是缓存过期后的行为,因为在某些情况下为了提升效率客户端会使用已经过期的缓存,如果服务端指定了Cache-Control: must-revalidate ,那么缓存过期后不能直接使用,必须进行再验证。no-cache不论缓存是否过期都需要客户端发起再验证。


Cache-Control: max-age ,指明了缓存的有效期,是一个相对时间,单位为秒

Expires ,指明了缓存的有效,是一个决定时间。HTTP 设计者后来认为,由于很多服务器的时钟都不同步,或者不正确,所以最好还是用剩余秒 数,而不是绝对时间来表示过期时间,已经不推荐使用。


客户端控制


上面我们介绍了,服务器端如何在响应头中添加响应的字段来浏览来是否可以使用缓存,同样,客户端自己也可以控制,以浏览器为例,这里我们主要说三个场景:


1.浏览器刷新

即我们按F5刷新页面的时候,该页面的http请求中会添加:Cache-Control:max-age:0, 即说明缓存直接失效啦,就不走缓存了,直接从服务器端读取数据。


2.浏览器强制刷新

即我们按ctrl+f5强制刷新页面的时候,该页面的http请求会添加:Cache-Control:no-cache; 即表示此时要首先去服务器端验证资源是否有更新,如果有更新则直接返回最新资源,如果没有更新,则返回304,然后浏览器端判断是304的话,则从缓存中读取数据。


3.浏览器前进后退重定向

当我们点击浏览器的前进后退操作时,这个时候请求中不会有Cache-Control的字段,没有该字段,就表示会检查缓存,直接利用之前的资源,不再重新请求服务器。


httpClient缓存代码分析


需要引入HttpClinet缓存模块

微信图片_20221114125339.png

测试代码如下:

public class CacheHttpClient {
  static CacheConfig cacheConfig =
    CacheConfig.custom().setMaxCacheEntries(1000).setMaxObjectSize(8192).build();
  static CloseableHttpClient cachingClient =
    CachingHttpClients.custom().setCacheConfig(cacheConfig).build();
  public static void main(String[] args) throws Exception {
    Scanner scanner = new Scanner(System.in);
    while (true) {
      scanner.nextLine();
      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;
          default:
            // do nothing
        }
      } finally {
        response.close();
      }
    }
  }
}

缓存的核心处理逻辑位于org.apache.http.impl.client.cache.CachingExec#execute中,如下:

微信图片_20221114125544.png

缓存处理的核心代码我在图中已经做了标注

1.是否启用缓存,代码很简单

image.png

2.从缓存中获取信息,这里的key实际就是访问时使用的URI,缓存底层默认使用的是一个Map

微信图片_20221114125635.png

3.缓存未命中时会向服务器发送真正的请求,代码简单,不做分析

4.缓存命中,这时要处理两种情况:「缓存未过期」、「缓存过期+再验证」

微信图片_20221114125708.png

对http协议了解后,这块的代码非常简单,所以笔者在这里也不赘述了


重定向


https://datatracker.ietf.org/doc/html/rfc2616#page-61

接下来我们聊聊重定向,跟重定向相关的响应码如下:

状态码

原因短语

含 义

301

Moved Permanently

在请求的 URL 已被移除时使用。响应的 Location 首部中应该包含 资源现在所处的URL,【301代表永久重定向】,客户端在后续访问时应该将URL替换为本次Location首部标明的URL

302

Found

【302代表临时重定向】,客户端后续访问时不需要进行替换,仍然应该使用原来的URL

303

See Other

其主要目的是允许 POST 请求的响应将客户端定向到某个资源上去

307

Temporary Redirect

也是临时重定向,跟302类似

你可能已经注意到 302、303 和 307 状态码之间存在一些交叉。这些状态码的用法有着细微的差别,大部分差别都源于 【HTTP/1.0 和 HTTP/1.1 应用程序对 这些状态码处理方式的不同】。


当 HTTP/1.0 客户端发起一个 POST 请求,并在响应中收到 302 重定向状态码时, 它会接受 Location 首部的重定向 URL,并向那个 URL 发起一个 GET 请求(而不 会像原始请求中那样发起 POST 请求)。


HTTP/1.0 服务器希望 HTTP/1.0 客户端这么做——如果 HTTP/1.0 服务器收到来自 HTTP/1.0 客户端的 POST 请求之后发送了 302 状态码,服务器就期望客户端能够接 受重定向 URL,并向重定向的 URL 发送一个 GET 请求。


问题出在 HTTP/1.1。HTTP/1.1 规范使用 303 状态码来实现同样的行为(服务器发 送 303 状态码来重定向客户端的 POST 请求,在它后面跟上一个 GET 请求)。


为了避开这个问题,HTTP/1.1 规范指出,对于 HTTP/1.1 客户端,用 307 状态码取 代 302 状态码来进行临时重定向。这样服务器就可以将 302 状态码保留起来,为 HTTP/1.0 客户端使用了。


HttpClient重定向代码分析


核心代码位于:org.apache.http.impl.execchain.RedirectExec#execute

image.png

重定向的处理策略都定义在redirectStrategy中,我们看下它的代码:

1.isRedirected方法,是否需要重定向

微信图片_20221114130138.png

实际就是判断状态码是不是我们前文提到过的301、302、303、307。

2.getRedirect方法,重定向时需要封装的请求信息:请求方法+URL

微信图片_20221114130209.png


写在最后


本来打算这篇文章作为《HTTP实战》的最后一篇的,实在太忙再加上篇幅原因,关于数据压缩、分块传输、范围请求就放到下篇文章吧~


参考:


《Http权威指南》


https://hc.apache.org/httpcomponents-client-4.5.x/current/tutorial/html/caching.html

https://datatracker.ietf.org/doc/html/rfc2616#page-74

https://datatracker.ietf.org/doc/html/rfc7232#page-13

https://www.digitalocean.com/community/tutorials/web-caching-basics-terminology-http-headers-and-caching-strategies

相关文章
|
4月前
|
缓存 安全 Android开发
Android经典实战之用Kotlin泛型实现键值对缓存
本文介绍了Kotlin中泛型的基础知识与实际应用。泛型能提升代码的重用性、类型安全及可读性。文中详细解释了泛型的基本语法、泛型函数、泛型约束以及协变和逆变的概念,并通过一个数据缓存系统的实例展示了泛型的强大功能。
45 2
|
2月前
|
存储 缓存 NoSQL
保持HTTP会话状态:缓存策略与实践
保持HTTP会话状态:缓存策略与实践
|
2月前
url重写重定向所有http网址到https网址
url重写重定向所有http网址到https网址
39 4
|
2月前
|
存储 缓存 监控
HTTP:强缓存优化实践
HTTP强缓存是提升网站性能的关键技术之一。通过精心设计缓存策略,不仅可以显著减少网络延迟,还能降低服务器负载,提升用户体验。实施上述最佳实践,结合持续的监控与调整,能够确保缓存机制高效且稳定地服务于网站性能优化目标。
56 3
|
3月前
|
数据安全/隐私保护 Docker 容器
配置Harbor支持https功能实战篇
关于如何配置Harbor支持HTTPS功能的详细教程。
139 12
配置Harbor支持https功能实战篇
|
3月前
|
分布式计算 Hadoop Devops
Hadoop集群配置https实战案例
本文提供了一个实战案例,详细介绍了如何在Hadoop集群中配置HTTPS,包括生成私钥和证书文件、配置keystore和truststore、修改hdfs-site.xml和ssl-client.xml文件,以及重启Hadoop集群的步骤,并提供了一些常见问题的故障排除方法。
93 3
Hadoop集群配置https实战案例
|
3月前
|
机器学习/深度学习 JSON API
HTTP协议实战演练场:Python requests库助你成为网络数据抓取大师
在数据驱动的时代,网络数据抓取对于数据分析、机器学习等至关重要。HTTP协议作为互联网通信的基石,其重要性不言而喻。Python的`requests`库凭借简洁的API和强大的功能,成为网络数据抓取的利器。本文将通过实战演练展示如何使用`requests`库进行数据抓取,包括发送GET/POST请求、处理JSON响应及添加自定义请求头等。首先,请确保已安装`requests`库,可通过`pip install requests`进行安装。接下来,我们将逐一介绍如何利用`requests`库探索网络世界,助你成为数据抓取大师。在实践过程中,务必遵守相关法律法规和网站使用条款,做到技术与道德并重。
59 2
|
3月前
|
数据采集 网络协议 API
HTTP协议大揭秘!Python requests库实战,让网络请求变得简单高效
【9月更文挑战第13天】在数字化时代,互联网成为信息传输的核心平台,HTTP协议作为基石,定义了客户端与服务器间的数据传输规则。直接处理HTTP请求复杂繁琐,但Python的`requests`库提供了一个简洁强大的接口,简化了这一过程。HTTP协议采用请求与响应模式,无状态且结构化设计,使其能灵活处理各种数据交换。
90 8
|
4月前
|
缓存 NoSQL 数据库
go-zero微服务实战系列(五、缓存代码怎么写)
go-zero微服务实战系列(五、缓存代码怎么写)
|
3月前
|
Python
HTTP协议不再是迷!Python网络请求实战,带你走进网络世界的奥秘
本文介绍了HTTP协议,它是互联网信息传递的核心。作为客户端与服务器通信的基础,HTTP请求包括请求行、头和体三部分。通过Python的`requests`库,我们可以轻松实现HTTP请求。本文将指导你安装`requests`库,并通过实战示例演示如何发送GET和POST请求。无论你是想获取网页内容还是提交表单数据,都能通过简单的代码实现。希望本文能帮助你在Python网络请求的道路上迈出坚实的一步。
72 0

热门文章

最新文章