squid中的时间和过期

2013年1月24日 发表评论 阅读评论

引言:

Squid作为一个缓存工具,其核心的功能就是缓存。那么判断一个obj是否缓存以及缓存多久就是极为重要的工作。事实上目前我们SQUID开发的很多内容都是和这个问题有关。Squid在过期时间处理上有其独有的细致一面:不可避免的就会引入复杂的一面。理解squid就必须理解过期时间处理。这也是用好squid的一个前提。

1. squid过期相关的基础知识

1.1 概述

谈论squid就不得不谈论HTTP,谈论HTTP则必须提及RFC2616.

RFC2616文档(http1.1协议)定义了一系列的规则,我们需要就这些规则来指导我们的行为(也许跟据需求做相反的事情)。

HTTP缓存被定义为:除去许多情况下的对发送请求的需求,和除去在其他许多情况下发送完整响应的需求。前者需要控制不必要的网络奔波去下载不需要的东西,而后者是控制对不需要的东西仅请求不下载。这就牵扯到过期机制的两个组成方式:截止机制和验证机制。

截止机制:通俗说就是过期时间。HTTP缓存效率最大值的表现。如果一个资源(URI)仅仅从本地缓存目录中提取而产生响应无疑是最省力的。换句话说,缓存能够不必首先联系服务器而返回响应。

验证机制:和截止机制相关的。即在截止机制中设置了一个过期时间。当超过这个时间时,会收到一个带有验证请求的访问发往缓存而不是一个正常请求。如果缓存中的副本未有变化,则采用304Not Modified来说明此问题。否则必须回复完整响应(包含实体body)。

1.2 Date与 Expires

Date和Expires都是表示绝对时间的概念,其不同点在于:

Date给出的是响应发出的绝对时间。

格式为:

“Date:” HTTP-date

Expires给出响应的内容过期的绝对时间。

格式为:

“Expires:” HTTP-date

例如,今天是3月25日,apache源站设置了

ExpiresActive on

ExpiresDefault “access plus 1 month”

那么请求该源站返回的header中就应该包括

Expires: Fri, 24 Apr 2009 08:00:57 GMT

注意:

a. Date与Expires都是绝对时间。

b. Date与Expires通常是格林尼治标准时间(如果后面带有GMT),也就是比北京时间早8个小时。

1.3 Age与max-age

这两个概念是比较容易搞混的。其相同点是:

a. 都是响应头的一部分

b. 都是一个时间长度,以秒为单位

但主要是不同点:

其中age是指:自从这个响应在源站服务器上生成以来(而不是源站内容修改以来!!),到现在所经历的秒数。

Age通常只对cache才有意义。

其格式为:

“Age:”age-value

max-age是指:一个响应被源站发出后,在cache当中存活的时间,换句话说,一个响应的Age值如果超过了max-age,就认为这个响应是过期的。

当然,max-age也是对于cache才有意义。

其格式为:

“Cache-control: max-age=” max-age-value

再次重申:max-age比Expires更加优先!

1.4 If-Modified-Since与Last-Modified

如果一个内容真的过期了,怎么办?从源站重新下载吗?

当然不。http协议对于过期的内容的处理,是先到源站验证一下,这个内容有没有发生改变,如果没有改变过,当然就不用重新下载了。这种验证是通过 If-Modified-Since等一系列http头实现的。

If-Modified-Since是http请求头的一部分,它表示客户端向源站询问“这个内容自从x年x月x日x时起,是否变过?”

其格式为:

“If-Modified-Since:” HTTP-date

如果源站发现该内容变过,则会返回一个200OK的响应,并把新的内容发回来给客户端。

如果源站发现内容没有变过,则会返回一个304的响应,告诉客户端“没有改变过,你的内容还是可以用的”,这种情况下就不用发送内容了,可以大大节省传输带宽。

注意:

a)如果客户端发的If-Modified-Since后面的日期是非法的日期,源站将直接返回200OK+新内容。

b) If-Modified-Since后面跟的日期是客户端上一次接到的响应中,Last-Modified的值。

Last-Modified是响应头的一部分,是源站给出的,一个内容在源站上最终更新的时间。

对于静态内容,Last-Modified是文件的更新时间,对于动态内容,取决于源站的具体实现。

其格式为:

“Last-Modified:” HTTP-date

1.5 Etag与If-None-Match

有的时候,Last-Modified 与 If-Modified-Since不能够可靠地标示内容的改变,这就需要Etag等更加可靠的打标签的机制。

Etag是响应头的一部分,是源站对内容所打的一个标签,用来标示这个文件,这个标签当且仅当内容变化才会变化,就像md5码一样。

与md5码不同的是,打Etag不需要读取整个文件的内容,比md5消耗的资源要少得多。

Etag起到的作用跟Last-Modified差不多,都是标示内容的变化,只是比Last-Modified更可靠。

If-None-Match是请求头的一部分,它表示客户端向源站询问“这个内容的标签还是不是xxxxxx?

如果源站发现该内容变过,则会返回一个200OK的响应,并把新的内容发回来给客户端。

如果源站发现内容没有变过,则会返回一个304的响应,告诉客户端“没有改变过,你的内容还是可以用的”,这种情况下就不用发送内容了,可以大大节省传输带宽。

2. 目前过期时间部分我们的squid是如何实现(修改)的

2.1 squid碰到了什么困境

如上的squid描述我们可以看出squid在处理过期时间方面的支持是很强大也很全面的。但我们仍然发现一些因源站给出错误header导致我们缓存过期的问题(通常出现此问题即出现连续过期)。很多客户囿于技术/策略问题,将控制权交给我们。此时,我们就需要squid理顺过期关系进行自维护的处理。

2.2 mod_use_server_date做了什么

mod_use_server_date做的最重要的一件事情,就是确定一个obj的“起始”时间。知道一个obj从什么时候“出生”,然后知道其生存时间,即可完全决定其在squid的生存时间。第二件重要的事情就是“推定”经过其他squid设备的obj的“起始”时间。下面画图说明此问题:

如上图所示,在菱形时间点发生了请求,下层去获取OBJ进入squid群组和过期时间。

从上图我们可以发现其中核心功能实现是max-age(或者由expire和date计算得到)。而多层squid之间的交流主要靠AGE。也就是说:

Max-age(或者由expires-date计算得到)决定OBJ生存时长

Age决定OBJ的出生时间点

2.3 expires和refresh_pattern哪个在生效

如上(2.2节)是use_server_date的设计大意。那么在复杂的网络条件下,如何知道“expires功能生效呢,还是refresh_pattern策略生效呢?

要回答这个问题,首先要确认的是:

配置的refresh_pattern, URL对应行是否配置override-expire:

1)如果配置了,refresh_pattern生效,忽略过期时间

2)如果没有,先检查过期时间,再检查refresh_pattern

目前我们的默认配置都是

ignore-reload 和override-lastmod(稍后讲解refresh_pattern时解释)所以可以不用注意如上问题。

如果确认如上refresh_pattern没有配置override-expire,则遵循如下规则:

如果源站给的信息可以计算出OBJ生存时间,则OBJ不走refresh_pattern

源站给的header可能:

1)有max_age

2)有expires和date

3)仅有expires

上述3者关系是顺序优先匹配,如果1符合就不需要2、3,同理2符合就不需要3.

满足此3项的为可计算生存时间的OBJ.

有如上3个条件符合所得出的过期时间也不尽相同。

squid的处理策略,

如果源站给的Header符合:

1)有max_age

2)有expires和date

则结果相同,过期时间是squid最初服务时间+max-age或者是squid最初服务时间+源站expire-源站date。

如果源站给的Header符合:

3)仅有expires

则以此header数据为准,绝对时间设置过期。

3. 目前的refresh_pattern使用情况和存在问题

3.1 refresh_pattern概述

refresh_pattern是squid.conf中关于过期的一种配置项。

通常如下格式:

refresh_pattern -i ^http 1440 0% 1440 ignore-reload override-lastmod

我们可以分解一行配置行为:

l 功能节名:refresh_pattern

l URL正则匹配区:-i ^http (-I含义为是否区分大小写)

l Age&lm-factore区:1440 0% 1440

l Options区:ignore-reload override-lastmod等

前二区目前没有疑问,下面就后二区详细介绍。

3.2 Age&lm-factore区

本区有3个配置节 分别为 min percentage max。

Min:是指一个object在缺少明确的Expires的情况下,能够确定的在cache中被认为新鲜分钟数(小于此值肯定是新鲜的)。这个参数推荐设为0,否则会造成动态应用中的内容被不正确地缓存住。

Max:是指一个object在缺少明确的Expires的情况下,在 cache中可能被认为新鲜的分钟数的最大值(大于此值肯定是过期的)

percentage是指,一个object在缺少明确的Expires的情况下,它的LM-factor的最大值(LM-factor超过此值则认为过期,否则新鲜)

LM-factor= (当前时间-到达cache的时间) / (到达cache的时间 – Last-Modified) * 100%

关于LM-factor,在《Squid: The Definitive Guide》一书中,有一个更加形象的图来说明这个概念。

LM-factor是HTTP协议中关于Last-Modifed时间参与过期计算的一个模糊处理过期时间的方式(如果不指明某URL过期时间)。显然在我们目前的应用下,是不该使用此项模糊策略的。我们目前线上机器配置percentage为0%,已经省略此功能节。

3.2 Options区

我们squid使用squid2.7,其options区目前可以有:

  1. override-expire: 强制min在expires前生效。
  2. override-lastmod: 强制min在lm-factor之前生效(在expire之后)。
  3. reload-into-ims:将no-cache或者reload请求转化为IMS请求给源站。
  4. ignore-reload:将no-cache或者reload请求头忽略。
  5. ignore-no-cache:强制忽略从源站而来的“Pragma: no-cache”和“Cache-control: no-cache”
  6. ignore-private:强制忽略从源站而来的“Cache-control: private”
  7. ignore-auth:强制将一个请求认为是源站发送的带有“Cache-control: public”
  8. stale-while-revalidate=NN:强制在过期时间生效后的NN秒内非过期
  9. ignore-stale-while-revalidate:强制忽略源站带有的“Cache-Control: stale-while-revalidate=NN”header
  10. max-stale=NN:强制将一个超过NN秒的OBJ设置为未缓存,即使其在cache,或者更新失败。
  11. negative-ttl=NN:强制此行refresh_pattern的negative_ttl时间,即使全局已经有过期时间设置。

3. SQUID 304的修改

Squid如果缓存了一个OBJ,且其未过期时,如果碰到客户端来请求更新此obj,则squid向下发送的304/Not Modified中的header不能进行更新(特别是Date和Expires),还是给源站给的。此时会导致客户的IE中的date和expires 显示为很早之前的(上层一直缓存的)。 在这种情况下源站不发送过期时间靠我们refresh_pattern进行判断的话,则不能刷新客户端的缓存记录时间。

此问题虽然可以使用update_headers来规避,但是显然其开销是非常大的。SQUID 304修改可以在无损状态下修复此问题。对于关闭update_headers导致304较多或者源站未给明确过期时间的请求,修改后都可以看到很明显

以上内容摘自于互联网。




本站的发展离不开您的资助,金额随意,欢迎来赏!

You can donate through PayPal.
My paypal id: itybku@139.com
Paypal page: https://www.paypal.me/361way

分类: 开源软件 标签:
  1. 本文目前尚无任何评论.