腾讯云 CDN 强制刷新 API 的使用

之前在《Github Pages 访问加速》一文中提到过我使用了腾讯云提供的 CDN(内容分发网络)加速服务(主要是每月送免费流量,不愧是良心云)。现在的主要问题是,博客更新与 CDN 缓存过期时间的矛盾,也就是网站更新的及时性与访问速度之间的矛盾(我没有在腾讯云的控制台找到手动刷新缓存的按钮)

更新于 2020-12-25:不知什么时候开始,腾讯云 CDN 更新了网页管理界面,新增了“刷新预热”功能,所以现在可以手动完成 URL 和目录的刷新了,但本文所介绍的 API 实现方案对完成自动化的 CDN 刷新仍有意义。

在 V2EX 上搜了搜解决方案,发现一位老哥提到了 CDN 服务商会提供 API。搜了一下,果然,尽管没有直接在网页前端做这个功能,但 API 是必不可少的:内容分发网络 API 概览 - 腾讯云

可以看到其中列出了大量操作腾讯云各项服务的 Action,包括我们关注的的刷新预热功能。可能要用到的 API 有:

  1. RefreshCdnUrl:删除 CDN 全网节点上缓存的指定资源(每一个账号每日可刷新 URL 10000 条,每次最多可提交 1000 条)

  2. RefreshCdnDir:用于将 CDN 全网节点上指定目录下的资源设置为过期(每一个账号每日可刷新目录 100 条,每次最多可提交 20 条)

  3. GetCdnRefreshLog:查询提交的刷新 URL、刷新目录任务执行情况

点击“查看调用示例”,可以看到腾讯云已经写好了 PHP、Python、Java、Go、nodeJs 等各种语言版本的调用代码,都放在了 QCloudCDN/CDN_API_DEMO 这个 repo 里。

这里我选择的是比较熟悉的 Python 版本。py 文件可以直接在腾讯云本地下载,或者去仓库里的 Qcloud_CDN_API/python 目录查看。Python 版本的 README 写得很详细,调用起来也很简单。

简单地说,就是下载 QcloudCdnTools_V2.py 文件时候用 shell 命令给它相应的参数调用就行了。实测这里使用的语法是 Python 2 的,且最好在 Linux 上运行。我的服务器恰好装了 Python 2.7,运行无误。

首先下载源代码文件:

1
wget https://raw.githubusercontent.com/QCloudCDN/CDN_API_DEMO/master/Qcloud_CDN_API/python/QcloudCdnTools_V2.py

然后在当前目录就可以直接调用它了。根据 README,上述的三个 API 功能的调用参数如下:

  1. RefreshCdnUrl

    1
    python QcloudCdnTools_V2.py RefreshCdnUrl -u xxxxx -p xxxxxxx --urls http://xxxxxxxtang.sp.oa.com/test.php --urls http://xxxxxxxtang.sp.oa.com/test1.php
    
  2. RefreshCdnDir

    1
    python QcloudCdnTools_V2.py RefreshCdnDir -u xxxxx -p xxxxxxx --dirs http://xxxxxxxtang.sp.oa.com/test/ --dirs http://xxxxxxxtang.sp.oa.com/a/ --dirs http://xxxxxxxtang.sp.oa.com/b/
    
  3. GetCdnRefreshLog

    1
    python QcloudCdnTools_V2.py GetCdnRefreshLog -u xxxxxxxxxxxx -p xxxxxxxxxxxx --startDate 2016-04-25 --endDate 2016-04-26
    

其中,-u 参数表示 SECRET_ID,-p 参数表示 SECRET_KEY, 可以在 https://console.qcloud.com/capi 生成。

如果执行时 Python 有 X509_up_ref 这样字眼的报错,多半是访问 https 资源前没有正确安装 pyOpenSSL:

1
pip install pyOpenSSL

从 API 的示例中也可以看出,RefreshCdnUrl 主要针对的是单个的资源地址,比如更改了一张图片或单个 html 的内容等情况;而 RefreshCdnDir 则针对的是整个文件目录下的所有文件(实测应该是递归的)。也就是说,如果单纯地想刷新整站流量地话,可以直接使用 RefreshCdnDir 对域名根目录进行刷新(不过注意频率,每天只能刷新 100 个目录哦)。

不过,按照官方语焉不详的说明,这个 API 所做的仅仅是标记指定的资源为“过期”,似乎并没有立刻再次从源服务器主动获取最新的资源,而要等到下次用户访问该资源时才会真正重新缓存。


自然而然地,可以想到:执行这样一句简单的调用 Python 程序的 shell 命令的时机是什么?当然,你可以添加计划任务,设定每隔一段时间自动刷新 CDN 缓存,但这样做无疑不够“智能”,因为博客可能几个月都不会更新,也可能一分钟内就更新好几次。最理想的状态是:每次更新 GitHub Pages,也就是对这个博客的 repo 进行 commit(push)时,自动触发此脚本刷新 CDN 缓存。

这让我想起了著名的 IFTTT。事实上,我所需的这种触发方式可以使用 Webhook

Webhook 是一个 API 概念,是微服务 API 的使用范式之一,也被成为反向 API,即前端不主动发送请求,完全由后端推送;举个常用例子,比如你的好友发了一条朋友圈,后端将这条消息推送给所有其他好友的客户端,就是 Webhook 的典型场景。

简单来说,Webhook 就是一个接收 HTTP POST(或 GET,PUT,DELETE)的 URL,一个实现了 Webhook 的 API 提供商就是在当事件发生的时候会向这个配置好的 URL 发送一条信息,与请求 - 响应式不同,使用 Webhook 你可以实时接受到变化。

GitHub 官方就提供了这样的功能,在自己的 repo 的设置里有一栏就是 Webhooks,具体细节可以参考 Webhooks | GitHub Developer Guide。简而言之:

When the specified events happen, we’ll send a POST request to each of the URLs you provide.

这里的 specified events 包含了你能想到的几乎一切关于 GitHub repo 的动作。

在 GitHub Web 端设置一个 Webhook 异常简单,默认用 push 作为触发条件的话,事实上只需要填写这个 Url 就行了(Secret 可以不需要)。这里我改成了使用 page_build,与 push 的区别在于仅监控 master 分支的 push。

但是,做到这里仅仅完成了工作的一小部分,所需的 Url 意味着需要使用自己的 VPS 作为后端来处理 Webhooks 的推送。具体的过程可以参考我的另一篇文章《使用 Node.js 实现 Webhook 的后端处理》

最后,稍微提一下新出的 GitHub Actions 服务,它可以说是 Webhooks 概念的升级版,是一个 CI/CD(持续集成/持续交付)工作流工具,简单地说,就是可以在仓库发生特定变化时直接在 GitHub 提供的操作系统级平台环境(可以是预装软件的 VPS,也可以是 Docker 镜像,甚至可以将自己的 VPS 作为 Self-hosted runners)中触发复杂的指令操作,也就是说可以不依赖自己的 VPS 就进行自动化操作(比如实现 hexo 博客系统的“类 Jekyll”式云端自动编译部署体验;自动完成新代码的编译测试发布等等)。不过对于一些轻量级的应用,Webhooks 足以胜任。

-------------本文结束    感谢您的阅读-------------
0%