在 HTTP 的响应 Header 信息中,以 X-
开头的字段表示的是自定义的扩展字段,这些字段不是由 HTTP 规范定义的,而是由上层应用自行定义和使用的。其中,X-Cache-Lookup
字段通常由 CDN 缓存服务器添加到响应头中,以提供关于缓存查找过程的相关信息。
本站目前使用的是 腾讯云 CDN,以腾讯云 CDN (指的是其「内容分发网络 CDN」产品)为例,启用后会在请求的响应头部增加两个字段:
- X-NWS-LOG-UUID
- X-Cache-Lookup
在腾讯云官方文档的 如何判断用户访问是否命中 CDN 节点缓存? 一节,解释了 X-Cache-Lookup
代表缓存命中的三个可能值:
X-Cache-Lookup: Hit From MemCache
X-Cache-Lookup: Hit From Disktank
X-Cache-Lookup: Cache Hit
如果不是以上三个值,则说明未命中缓存。但实际测试的结果和文档中描述的不太一致。
实际测试结果
命中缓存的情况
chuan@MacBook ~ % curl -I https://kanchuan.com/static/site/me.png
HTTP/1.1 200 OK
Last-Modified: Thu, 16 Jan 2020 05:39:24 GMT
Etag: "5e1ff70c-5251"
Server: nginx
Date: Tue, 13 Jun 2023 07:56:41 GMT
Content-Type: image/png
Cache-Control: public, max-age=2592000
Age: 1967830
Content-Length: 21073
Accept-Ranges: bytes
X-NWS-LOG-UUID: 13733582990050331190
Connection: keep-alive
X-Cache-Lookup: Cache Hit
X-Cache-Lookup
的值为 Cache Hit
,符合预期。
未命中缓存的情况
为了说明问题,我在网站根目录新建了一个 cdn-test.html 文件,理论上第一次访问不会命中缓存,后续访问才会命中。下面是测试结果:
首次访问:
chuan@MacBook ~ % curl -I https://kanchuan.com/cdn-test.html
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 06 Jul 2023 08:09:24 GMT
Content-Type: text/html
ETag: "64a67699-d"
Strict-Transport-Security: max-age=63072000
X-Cache-Lookup: Cache Miss
X-Cache-Lookup: Hit From Inner Cluster
Last-Modified: Thu, 06 Jul 2023 08:08:57 GMT
Content-Length: 13
Accept-Ranges: bytes
X-NWS-LOG-UUID: 3394639510813525881
Connection: keep-alive
X-Cache-Lookup: Cache Miss
第二次访问:
chuan@MacBook ~ % curl -I https://kanchuan.com/cdn-test.html
HTTP/1.1 200 OK
Last-Modified: Thu, 06 Jul 2023 08:08:57 GMT
Etag: "64a67699-d"
Server: nginx
Date: Thu, 06 Jul 2023 08:09:24 GMT
Content-Type: text/html
Strict-Transport-Security: max-age=63072000
Content-Length: 13
Accept-Ranges: bytes
X-NWS-LOG-UUID: 9328899840739050300
Connection: keep-alive
X-Cache-Lookup: Cache Hit
可以看到在命中缓存的情况下,只出现了一次 X-Cache-Lookup
且值为 Cache Hit
,这个符合预期。但首次请求未命中缓存时,返回了多个X-Cache-Lookup
,且出现了值为 Hit From Inner Cluster
的情形。
另外,未能测试出 Hit From MemCache
和 Hit From Disktank
的情况。
CDN 是多层级的缓存系统
传统的缓存机制,出现「Cache Miss」表示缓存系统未能找到匹配的缓存对象,会直接从源服务器获取响应,这个过程就是俗称的「回源」。但目前主流的 CDN 系统都是多层级的缓存结构,典型的就是包含「边缘节点」和「中心节点」的系统:
- 直接面向用户提供内容 Cache 的服务器部署在 CDN 系统的边缘位置,称之为「边缘节点」;
- 「中心节点」直接和源站交互,缓存了完整的源站内容并负责管理 CDN 网络、内容更新、策略分发等。
普通用户通过 CDN 网络请求源站的某一个资源时,请求会首先达到「边缘节点」;当「边缘节点」没有缓存时,会向「中心节点」请求;当「中心节点」也没有缓存时,才会回源请求源站,这样一级一级地请求并一级一级地原路返回将内容传输给终端用户。
Hit From Inner Cluster
是什么意思?
实际运行的 CDN 网络则更加复杂,在前例中的「首次访问」的结果中,一次响应中出现了三次 X-Cache-Lookup
,说明这次请求经过了三个 CDN 节点,前两个节点都是 Cache Miss
即没有命中缓存,最后一个 Hit From Inner Cluster
从字面上看意思是从内部集群系统中找到了匹配对象,我对此不太理解,但也没有查到相关的说明。从测试表现上看,Hit From Inner Cluster
表达的含义似乎是 “CDN 网络中没有查到缓存,但已经向源站发起请求”。得出这个结论的依据是,php
服务的动态内容是不缓存的,但一样会出现Hit From Inner Cluster
:
chuan@MacBook ~ % curl -I https://kanchuan.com
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 06 Jul 2023 09:43:16 GMT
Content-Type: text/html; charset=UTF-8
Vary: Accept-Encoding
Strict-Transport-Security: max-age=63072000
X-Cache-Lookup: Cache Miss
X-Cache-Lookup: Hit From Inner Cluster
Transfer-Encoding: chunked
Accept-Ranges: bytes
X-NWS-LOG-UUID: 5158878277662562061
Connection: keep-alive
X-Cache-Lookup: Cache Miss
CDN 总是会获得加速效果吗?
对于静态内容,CDN 网络会在离用户最近的那个「边缘节点」响应请求,在大部分情况下加速效果明显。但如果「边缘节点」离用户过远,反而会变使请求变得更慢。比如国外的 CloudFlare,由于其免费产品在中国大陆没有节点,导致从国内访问会异常缓慢:用户的请求先要经过香港节点,请求包要绕大半个地球才能响应给用户,速度不可能很快。
另外,对于 PHP 页面这样的动态内容,使用 CDN 的效果往往是负面的。下面做个简单的测试。
不启用 CDN 缓存
强制设置本地 host,让域名请求直接抵达源站,打印请求的响应时间:
chuan@MacBook ~ % curl -I https://kanchuan.com -w %{time_starttransfer}
HTTP/2 200
...
0.075738
启用 CDN
取消本地 host 设置,让域名请求先抵达 CDN 网络,打印请求的响应时间:
chuan@MacBook ~ % curl -I https://kanchuan.com -w %{time_starttransfer}
HTTP/1.1 200 OK
...
0.165663
可以看到,使用 CDN 网络之后请求耗时反而大幅增加。由于经过了多个 CDN 节点,相当于请求被转发了 N 次,每一次的耗时累加起来比直接请求返回要多。
如何减少 X-Cache-Lookup 的次数?
响应中每出现一次 X-Cache-Lookup
即表示经过了一个 CDN 节点,对于 PHP 页面这样动态的内容来说,我们希望每次请求都直接回源,不需要再经过其它 CDN 节点了,最优的效果是响应中仅出现一次 X-Cache-Lookup
。理论上应该是这样,但没有在腾讯云的后台管理界面和文档中找到有相关的设置项,不确定是不支持还是我没有找到。
以上是我对腾讯云 CDN 的一些使用理解,文章中留下的两个疑问如果有正确答案的朋友可以在留言中指正说明。
Hit From Inner Cluster
的正确含义;- 如何设置减少
X-Cache-Lookup
出现的次数。
留言板