资源阿里云CDN预热优化

541 阅读9分钟

背景

海外用户访问国内的图片时,需要回源站拉图。由于海外许多国家网络基础设施较差,网速不行,图片回源时间可能会很长,导致很多图片慢加载。

这里有两个优化点:

  • 对图片进行压缩,减少拉图片的流量。
  • 对压缩后的图片进行预热,让图片提前到达对应国家的 CDN 结点上,缩短图片与用户的物理距离。

阿里云CDN拓扑图

目前使用了阿里云的 CDN 服务,其结点分布拓扑图如下所示。

这里有几个点:

  • 阿里云的 CDN 分了层级,对用户外分为 L1 结点、L2 结点和源站。源站是提供资源的服务器,可以是自己的 Nginx 服务器,也可以指定为 OSS 的桶,这样就能直接去阿里云的 OSS 拉取图片。L2 是中间的结点,全球范围内,小国家可能一个国家仅一个 L2 结点,大国家可能有几个。L1 是用户能够直接访问的 CDN 结点,一个国家可能会存在多个,一个 L2 结点会映射到多个 L1 结点。
  • 用户通过 CDN 域名请求资源时,该 CDN 域名会被 DNS 服务器解析到最佳的 L1 结点,如果 L1 上已经缓存了资源则直接返回,否则会查询 L2,如果 L2 也没资源则回源查询资源。如果是 L1 回源查询数据,那拿到源站资源后只会缓存到 L1 结点,L2 结点依然没有数据。

CDN资源预热

阿里云的 CDN 提供资源刷新与预热功能。

通过刷新功能,您可以删除 CDN 节点上已经缓存的资源,并强制 CDN 节点回源站获取最新资源,适用于源站资源更新和发布、违规资源清理、域名配置变更等;通过预热功能,您可以在业务高峰前预先将热门资源缓存到 CDN 节点,降低源站压力提升用户体验。

参考文档:help.aliyun.com/document_de…

注意:预热资源是预热到 L2 CDN 结点,此时 L1 即可去 L2 拉资源而无需回源。

阿里云控制台可以实现小规模资源的刷新和预热,对于有大量资源需要预热或者刷新的场景,阿里云提供了相关接口进行自动化操作。参考文档:next.api.aliyun.com/document/Cd…

预热需要鉴权,不要在代码里面明文配 AccessKey 相关的信息。

预热接口需要指定预热的 URL,每次预热会生成一个 Task,预热结果也可以在 阿里云 控制台查看。

image.png

指定CDN结点获取资源

由于人在国内,有需求是想测试一下看看国外的 CDN 结点回国内源站拉取资源的表现,这里介绍下方法。

首先,通过下面的网站(查询全球的公共 DNS 服务器)找一个 DNS 的服务器,看看自己的 CDN 域名会被解析到哪里。

public-dns.info/#countries

image.png 随便选一个澳大利亚的:

image.png

用 nslookup 请求这个 DNS 服务器,看看自己的域名会解析到哪个服务器。

# cm-res.cretacontent.com 是自己的CDN域名
# 116.251.31.224 是DNS服务器的IP
$ nslookup cm-res.cretacontent.com 116.251.31.224                                                                                        
Server:		116.251.31.224
Address:	116.251.31.224#53

Non-authoritative answer:
cm-res.cretacontent.com	canonical name = cm-res.cretacontent.com.cdn.dnsv1.com.
cm-res.cretacontent.com.cdn.dnsv1.com	canonical name = 0it6b9ua.ovslegodl.sched.ovscdns.com.
Name:	0it6b9ua.ovslegodl.sched.ovscdns.com
Address: 101.33.26.242
Name:	0it6b9ua.ovslegodl.sched.ovscdns.com
Address: 43.132.81.29
Name:	0it6b9ua.ovslegodl.sched.ovscdns.com
Address: 43.132.80.22
Name:	0it6b9ua.ovslegodl.sched.ovscdns.com
Address: 43.132.80.30

可以看到给出了一系列可能的 CDN 结点地址,在自己的 /etc/hosts 文件加一下解析规则,让到 "cm-res.cretacontent.com" 域名的请求全部解析到指定的 IP:

43.132.81.29 cm-res.cretacontent.com

这样即可实现向指定 CDN 服务器发起请求,这样即使是本地请求,也会去上述 CDN 服务器(L1 结点)发起请求,如果该 L1 结点上没有资源,则由该 L1 结点回源请求资源。

CDN结点资源请求实验

如何能够确定一个资源已经预热到了 CDN 结点上?答案是通过 HTTP 的响应码进行判断。

具体方式为看 via header. 举个例子:

via: cache6.l2vn1[0,0,200-0,H], cache1.l2vn1[0,0], cache5.vn17[0,0,200-0,H], cache3.vn17[1,0]

这里 via 会给出 L1 和 L2 结点的资源缓存命中情况。cache6.l2vn1 表示 L2 结点,cache5.vn17 表示 L1 结点。对应的中括号里面,H 表示 命中,M 表示未命中。

基于上述方式,在本地浏览器请求一下国外(配置了越南的 CDN 服务器)的 L1 CDN 结点,看看响应情况。

(1)不预热图片实验

不进行图片预热。图片ID:18552bbcb55c642

请求一个越南的L1结点(IP: 128.1.60.231)

首次请求(请求时间:16:45分):

ali-swift-global-savetime: 1672130751
cache-control: max-age=31536000
date: Tue, 27 Dec 2022 08:45:51 GMT
via: cache1.l2vn1[248,247,200-0,M], cache37.l2vn1[249,0], cache7.vn17[250,250,200-0,M], cache1.vn17[251,0]
x-cache: MISS TCP_MISS dirn:-2:-2
x-swift-cachetime: 93312000
x-swift-savetime: Tue, 27 Dec 2022 08:45:51 GMT

再次请求(请求时间:16:47分):

ali-swift-global-savetime: 1672130751
cache-control: max-age=31536000
date: Tue, 27 Dec 2022 08:45:51 GMT
via: cache1.l2vn1[248,247,200-0,M], cache37.l2vn1[249,0], cache7.vn17[0,0,200-0,H], cache1.vn17[0,0]
x-cache: HIT TCP_MEM_HIT dirn:13:793742575
x-swift-cachetime: 93312000
x-swift-savetime: Tue, 27 Dec 2022 08:45:51 GMT

实验结论:

  • 首次请求 L1 结点,L1 未命中资源缓存,此时会回源拉取图片,然后缓存到 L1 上,但是没有缓存到 L2 上(这里不排除阿里云可能还做了次数的统计,也许请求的次数多了就会缓存到 L2 了)!
  • 再次请求 L1 结点,资源成功缓存到 L1 上。

(2)图片预热实验

直接调用阿里云的预热接口对图片进行预热. 图片ID:185526c5bf5fcd3

预热时间:2022-12-27 16:01:13:105

预热后等待一段时间后,再通过 CDN 结点获取图片(根据测试结果,一般预热后20秒内可以实现全球预热)。

请求越南胡志明的L1结点(IP: 128.1.60.231)

首次请求(请求时间:16:17分):

ali-swift-global-savetime: 1672128077
cache-control: max-age=31536000
date: Tue, 27 Dec 2022 08:01:17 GMT		# 这里date是预热时间
via: cache6.l2vn1[0,0,200-0,H], cache1.l2vn1[0,0], cache5.vn17[2,1,200-0,M], cache3.vn17[3,0]
x-cache: MISS TCP_MISS dirn:-2:-2
x-swift-cachetime: 93311037
x-swift-savetime: Tue, 27 Dec 2022 08:17:20 GMT

再次请求(请求时间:16:19分):

ali-swift-global-savetime: 1672128077
cache-control: max-age=31536000
date: Tue, 27 Dec 2022 08:01:17 GMT
via: cache6.l2vn1[0,0,200-0,H], cache1.l2vn1[0,0], cache5.vn17[0,0,200-0,H], cache3.vn17[1,0]
x-cache: HIT TCP_MEM_HIT dirn:12:391635488
x-swift-cachetime: 93311037
x-swift-savetime: Tue, 27 Dec 2022 08:17:20 GMT

结果分析:

  • date 表示了资源预热到 L2 的时间。
  • L2 结点缓存命中(H),预热成功;L1 结点未命中(M)。说明首次访问这个 L1 结点时没有资源,这时到 L2 结点获取资源,且命中了 L2 中的资源,之后再将资源缓存到 L1 上。
  • 再次请求时,L1 也已经缓存了这个资源,此时 L1 也是缓存命中(H).

请求另一个越南胡志明的L1结点(IP: 107.155.62.89)

首次请求(请求时间:16:22分):

ali-swift-global-savetime: 1672128077
cache-control: max-age=31536000
date: Tue, 27 Dec 2022 08:01:17 GMT
via: cache6.l2vn1[0,0,200-0,H], cache29.l2vn1[1,0], cache14.vn15[2,2,200-0,M], cache10.vn15[3,0]
x-cache: MISS TCP_MISS dirn:-2:-2
x-swift-cachetime: 93310746
x-swift-savetime: Tue, 27 Dec 2022 08:22:11 GMT

再次请求(请求时间:16:23分):

ali-swift-global-savetime: 1672128077
date: Tue, 27 Dec 2022 08:01:17 GMT
via: cache6.l2vn1[0,0,200-0,H], cache29.l2vn1[1,0], cache14.vn15[0,-1,200-0,H], cache10.vn15[2,0]
x-cache: HIT TCP_MEM_HIT dirn:13:418829285
x-swift-cachetime: 93310746
x-swift-savetime: Tue, 27 Dec 2022 08:22:11 GMT

结果分析:

  • 表现与前一个胡志明的 L1 结点一致,资源被成功预热到越南的 L2 结点。

再请求一个加拿大的L1结点(IP: 47.246.24.215)

首次请求(请求时间:16:35分):

ali-swift-global-savetime: 1672128079
cache-control: max-age=31536000
date: Tue, 27 Dec 2022 08:01:19 GMT		# 预热时间 加拿大预热完成时间晚2秒
via: cache22.l2us1[0,0,200-0,H], cache7.l2us1[0,0], ens-cache10.us18[2478,2477,200-0,M], ens-cache16.us18[2481,0]
x-cache: MISS TCP_MISS dirn:-2:-2
x-swift-cachetime: 93309944
x-swift-savetime: Tue, 27 Dec 2022 08:35:35 GMT

再次请求(请求时间:16:36分):

ali-swift-global-savetime: 1672128079
cache-control: max-age=31536000
date: Tue, 27 Dec 2022 08:01:19 GMT
via: cache22.l2us1[0,0,200-0,H], cache7.l2us1[0,0], ens-cache10.us18[0,0,200-0,H], ens-cache16.us18[1,0]
x-cache: HIT TCP_MEM_HIT dirn:12:103600147
x-swift-cachetime: 93309944
x-swift-savetime: Tue, 27 Dec 2022 08:35:35 GMT

实验结论:

  • 加拿大物理距离更远,资源预热成功时间比越南稍晚。
  • 资源成功预热到加拿大的 L2 结点,能够实现全球预热。

(3)URL带参数预热实验

测试预热一个带自定义参数的图片,图片 ID:185588f9885b673

预热URL(这里参数是随意定的):cm-res.cretacontent.com/api/apolo-i…

这里就不贴测试结果了。

结论:CDN 预热是以 URL 为资源的 Key 进行缓存的,只要 URL 有任何改变,都会导致 CDN 进行回源请求。因此图片压缩预热时,一定要预设好图片的宽高和质量等参数,后面不要调整,否则所有请求都会穿透 CDN 回源站。