OpenResty Edge 在网关(Edge Node)上缓存 HTTP 响应,命中缓存的请求无需再回源到后端,从而降低源站压力和响应延迟。你只需在页面规则里打开代理缓存开关、设置缓存键,再发布到每台网关节点即可,全程无需改动 Nginx 配置、也无需 reload。本文演示完整步骤,并用 curl 逐一验证 Cache-Status: HITMISS,最后展示如何在源站不返回 Cache-Control 头时也强制缓存。

缓存未命中时,Edge 节点将请求转发到后端服务器

当客户端请求命中 Edge Node 服务器上的缓存时,不需要向后端服务器发送请求。这样可以减少响应延迟,节省网络带宽——这也正是用 OpenResty Edge 构建私有 CDN 的核心机制。

缓存命中时,Edge 节点直接返回响应,不再回源

在页面规则中启用代理缓存并设置缓存键

让我们进入 OpenResty Edge 的 Admin Web 控制台。这是我们控制台的样本部署。每个用户都有自己的本地部署。

我们可以继续之前的应用例子,test-edge.com

OpenResty Edge Admin Web 控制台首页

我们已经定义了一个上游。

已定义一个后端上游的上游列表

这个 my_backend 上游只有 1 个后台服务器。

只配置了一台后端服务器的 my_backend 上游

注意后台服务器的 IP 地址以 191 结尾。我们之后会用到这个 IP 地址。

以 191 结尾的后端服务器 IP 地址

而且我们也已经定义了一个页面规则。

已定义一条页面规则的页面规则列表

这个页面规则设置了一个反向代理指向这个上游。

该页面规则配置为指向上游的反向代理

显然,我们还没有为这个页面规则启用代理缓存。

现在让我们编辑这个页面规则,在网关中添加响应缓存。

编辑页面规则以添加代理缓存

让我们启用代理缓存。

在页面规则中打开代理缓存开关

这里我们可以配置缓存键。

为代理缓存配置缓存键

默认情况下,缓存键由两部分组成:URI,和查询字符串(URI 参数)。

你也可以选择使用其他种类的键的组分。

选择其他缓存键组分

可选的缓存键组分类型列表

或者我们可以将整个查询字符串从键中删除。

将查询字符串从缓存键中删除

我们还可以添加更多的键组分。

向缓存键中添加更多组分

在这个例子中,我们将只保留默认的缓存键定义。

保存此页面规则。

保存已启用代理缓存的页面规则

让我们发布新的配置。

为待发布变更创建新版本

把我们刚才的变更推送出去。

推送前查看待发布的变更

发布!

确认发布以推送变更

我们的新版配置现在已经同步到我们所有的网关服务器了。

新版配置已同步到所有网关服务器

我们的配置更改不需要重新加载服务器、重新启动或二进制升级服务器进程。所以它的效率非常高。

配置变更无需 reload 即可下发到网关节点

用 curl 测试缓存并验证 Cache-Status HIT/MISS

我们来测试一下网关服务器的缓存。

OpenResty Edge 控制台中的网关服务器列表

我们复制一下这个旧金山网关服务器的 IP 地址。

复制旧金山网关服务器的 IP 地址

注意这个 IP 地址的最后的数字是 133 。

在终端上,我们通过 curl 命令行工具向这个网关服务器发送 HTTP 请求。

curl -I -H 'Host: test-edge.com' http://138.68.231.133/

注意返回的 Cache-Status: MISS 响应头。

curl 响应中返回的 Cache-Status: MISS 头

再试一次。

curl -I -H 'Host: test-edge.com' http://138.68.231.133/

我们仍然收到 Cache-Status: MISS 头。这意味着缓存根本没有被使用。这是为什么呢? 原来后端服务器的原始响应头里缺少 ExpiresCache-Control 这样的头。

第二次请求仍然返回 Cache-Status: MISS

我们可以登录到后台服务器。

ssh ec2-user@54.213.103.191

记得后台服务器的 IP 地址是以 191 结尾的。

登录到 IP 以 191 结尾的后端服务器

这个后台服务器运行的是开源的 OpenResty 软件。

ps aux | grep nginx

后端运行着开源 OpenResty 的 nginx 进程

后台服务器可以运行任何其他的使用 HTTP 协议的软件。

任何支持 HTTP 协议的软件都可作为 Edge 后端

我们可以直接向这个后台服务器发送测试请求。

curl -I -H 'Host: test-edge.com' http://127.0.0.1/

请注意,我们正在访问本地主机。

通过 curl 直接向本地后端发送请求

好吧,它确实没有提供任何 ExpiresCache-Control 的响应头。

后端响应中没有 Expires 或 Cache-Control 头

现在让我们重新配置我们的后台服务器。

cd /usr/local/openresty/nginx/

打开 nginx 配置文件。

sudo vim conf/nginx.conf

找到我们的根,location /

在 nginx 配置文件中找到根 location 块

并增加 1 小时的过期时间。

expires 1h;

需要注意的是,后台服务器可以针对不同的 location 定义不同的过期时间。或者对某些响应完全禁用缓存。

在后端 location 块中添加 expires 1h 指令

保存并退出文件。

测试 nginx 配置文件是否正确。

sudo ./sbin/nginx -t

没有问题。

用 nginx -t 测试 nginx 配置文件

现在重新加载后端服务器进程。

sudo kill -HUP `cat logs/nginx.pid`

用 HUP 信号 reload 后端 nginx 服务器

注意,对于开源的 Nginx 服务器,配置方法也是一样的。

现在可以测试后台服务器了。

curl -I -H 'Host: test-edge.com' http://127.0.0.1/

好了,现在它响应头里有 ExpiresCache-Control 这两个了。

后端现在返回 Expires 和 Cache-Control 头

现在将请求发送给网关服务器。

curl -I -H 'Host: test-edge.com' http://138.68.231.133/

它仍然显示的是 Cache-Status: MISS 头。

向网关发送的首个请求返回 Cache-Status: MISS

这是一次预期中的缓存不命中。因为这是我们发的第一个请求。

首个请求未命中缓存、回源到后端的示意图

再次发送请求。

curl -I -H 'Host: test-edge.com' http://138.68.231.133/

太好了!我们终于看到了 Cache-Status: HIT 头!

向网关发送的第二个请求返回 Cache-Status: HIT

终于如愿以偿地命中了缓存。

第二个请求命中缓存、不再回源的示意图

如果我们添加一个查询字符串。

curl -I -H 'Host: test-edge.com' 'http://138.68.231.133/?a=3'

注意 a=3 的部分。

带 a=3 查询字符串的请求返回缓存未命中

那么又会再次出现缓存不命中。

这是因为默认的缓存键包括查询字符串。

查询字符串是默认缓存键的一部分,导致未命中

再次运行相同的请求应该就能命中缓存了。

curl -I -H 'Host: test-edge.com' 'http://138.68.231.133/?a=3'

确实是被缓存命中了。如果你不关心这个查询字符串,你可以把它从缓存键中删除。

重复发送带查询字符串的请求返回缓存命中

源站无 Cache-Control 头时强制缓存

有时候我们就是懒得去改变后台服务器的配置。 那么我们也可以在源站响应没有出现任何缓存控制头的情况下,默认就对响应进行强制缓存。

我们可以修改我们原来的页面规则来实现这个功能。

开启默认强制缓存。

在页面规则中开启默认强制缓存

还可以设置可缓存响应状态码的默认过期时间。

设置可缓存响应状态码的默认过期时间

我们将在另一个视频中演示这个功能。响应缓存下来之后,当源站内容变化时,你还可以实时清除 HTTP 缓存

常见问题

启用代理缓存后,为什么 OpenResty Edge 仍然返回 Cache-Status: MISS?

启用代理缓存后仍然是 Cache-Status: MISS,通常说明源站响应本身不可缓存。本例中后端没有返回 ExpiresCache-Control 头,所以网关不会缓存它。在后端 location 里加上 expires 1h;,源站就会带上这些响应头,此后第二次请求便会返回 Cache-Status: HIT

后端不返回 Cache-Control 头时,如何缓存响应?

编辑页面规则、开启默认强制缓存,网关就会在源站不返回缓存控制头时也缓存响应,你再为可缓存的响应状态码设置默认过期时间即可。这样无需改动后端服务器的任何配置,就能在边缘完成缓存。

为什么加上查询字符串会导致缓存未命中?

默认缓存键由 URI 加查询字符串组成,因此带 ?a=3 的请求与不带它的请求是两个不同的键,首次访问会未命中缓存;再次发送同样的请求就会命中。如果查询字符串不影响响应内容,可以把它从缓存键中删除,让所有变体共用同一份缓存。

修改 OpenResty Edge 缓存配置需要 reload 或重启 Nginx 吗?

不需要。启用代理缓存并发布变更后,配置会同步到每一台网关服务器,无需 reload、重启或二进制升级服务器进程,新的缓存行为即时生效、不中断服务。

关于 OpenResty Edge

OpenResty Edge 是一款专为微服务和分布式流量架构设计的全能型网关软件,由我们自主研发。它集流量管理、私有 CDN 构建、API 网关、安全防护等功能于一体,帮助您轻松构建、管理和保护现代应用程序。OpenResty Edge 拥有业界领先的性能和可扩展性,能够满足高并发、高负载场景下的苛刻需求。它支持调度 K8s 等容器应用流量,并可管理海量域名,轻松满足大型网站和复杂应用的需求。

如果你喜欢这个教程,请订阅这个博客网站和我们的 YouTube 频道B 站频道。谢谢!

关于作者

章亦春是开源 OpenResty® 项目创始人兼 OpenResty Inc. 公司 CEO 和创始人。

章亦春(Github ID: agentzh),生于中国江苏,现定居美国湾区。他是中国早期开源技术和文化的倡导者和领军人物,曾供职于多家国际知名的高科技企业,如 Cloudflare、雅虎、阿里巴巴, 是 “边缘计算“、”动态追踪 “和 “机器编程 “的先驱,拥有超过 22 年的编程及 16 年的开源经验。作为拥有超过 4000 万全球域名用户的开源项目的领导者。他基于其 OpenResty® 开源项目打造的高科技企业 OpenResty Inc. 位于美国硅谷中心。其主打的两个产品 OpenResty XRay(利用动态追踪技术的非侵入式的故障剖析和排除工具)和 OpenResty Edge(最适合微服务和分布式流量的全能型网关软件),广受全球众多上市及大型企业青睐。在 OpenResty 以外,章亦春为多个开源项目贡献了累计超过百万行代码,其中包括,Linux 内核、Nginx、LuaJITGDBSystemTapLLVM、Perl 等,并编写过 60 多个开源软件库。

关注我们

如果您喜欢本文,欢迎关注我们 OpenResty Inc. 公司的博客网站 。也欢迎扫码关注我们的微信公众号:

我们的微信公众号

翻译

我们提供了英文版原文和中译版(本文) 。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!