前情:

在上一篇建站记录系列文章中,我们为博客源服务器配置了CDN加速,但是实际使用中发现,我们推送代码,自动构建生成的新包发到服务器后,我们使用域名访问站点,内容缺没有更新,这是为什么呢?实际上是因为站点资源更新后,CDN没有及时回源进行缓存刷新。

我使用的CDN产品是在腾讯云搞活动买服务器时顺便买的EdgeOne,好像是50块钱一年,据说是新一代的CDN,多了DDos攻击防御和CC攻击功能,但是我用的是活动版就享受不到这些功能了,估计等这个到期了还是要换回更便宜的常规CDN,这个正常价续费太贵了,我等一般人实在用不起啊。😂,下面就以EdgeOne为例,记录下我的优化过程。

两种实现思路:

  1. 在服务器端监听文件变化,如果有文件推送,则调用腾讯云API刷新CDN缓存;
  2. 通过GithubAction实现:在代码推送到远程仓库后,触发Action工作流,调用腾讯云API实现CDN缓存刷新;

相关知识补充:

1.什么是腾讯云API?

在本文的需求中,腾讯云API是实现CDN缓存刷新的关键工具,它是腾讯云提供的实现其一系列产品操作的网络接口,通过调用这些接口,开发者可以实现自己想要的功能,比如我们想要实现的CDN在代码推送后的自动刷新;

2.什么是腾讯云SDK?

腾讯云SDK是腾讯云开发团队对其API的再次封装,包括各种语言,参考官网的截图,本文使用了其中的Nodejs版本,通过SDK调用API更方便,只需关注参数,不用关注更多API请求、数据格式层面的细节。

动手实践:

💡关于GithubAction的使用在我之前的文章有介绍,不了解的读者可以先移步阅读:https://cyanfish.site/bdd56b8f

关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 调用腾讯云sdk刷新cdn缓存,注意替换关键参数配置
ClearCDNCache:
needs: scpToServer
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16' # 指定 Node.js 版本

- name: Install dependencies
run: npm install tencentcloud-sdk-nodejs

- name: Purge Cache with Tencent SDK
env:
TENCENT_CLOUD_SECRET_ID: ${{ secrets.TENCENT_CLOUD_SECRET_ID }}
TENCENT_CLOUD_SECRET_KEY: ${{ secrets.TENCENT_CLOUD_SECRET_KEY }}
run: |
# 创建一个临时的 JS 文件用于执行腾讯云 API 请求
echo 'const tencentcloud = require("tencentcloud-sdk-nodejs");' > clearCache.js
echo 'const TeoClient = tencentcloud.teo.v20220901.Client;' >> clearCache.js
echo 'const clientConfig = {' >> clearCache.js
echo ' credential: {' >> clearCache.js
echo ' secretId: process.env.TENCENT_CLOUD_SECRET_ID,' >> clearCache.js
echo ' secretKey: process.env.TENCENT_CLOUD_SECRET_KEY,' >> clearCache.js
echo ' },' >> clearCache.js
echo ' region: "ap-chengdu",' >> clearCache.js
echo ' profile: {' >> clearCache.js
echo ' httpProfile: {' >> clearCache.js
echo ' endpoint: "teo.tencentcloudapi.com",' >> clearCache.js
echo ' },' >> clearCache.js
echo ' },' >> clearCache.js
echo '};' >> clearCache.js

echo 'const client = new TeoClient(clientConfig);' >> clearCache.js
echo 'const params = {' >> clearCache.js
echo ' Targets: ["www.yourdomin.com"],' >> clearCache.js
echo ' Type: "purge_host",' >> clearCache.js
echo ' ZoneId: "yourSiteZoneId",' >> clearCache.js
echo '};' >> clearCache.js

echo 'client.CreatePurgeTask(params).then(' >> clearCache.js
echo ' (data) => {' >> clearCache.js
echo ' console.log(data);' >> clearCache.js
echo ' },' >> clearCache.js
echo ' (err) => {' >> clearCache.js
echo ' console.error("error", err);' >> clearCache.js
echo ' }' >> clearCache.js
echo ');' >> clearCache.js

# 运行该脚本
node clearCache.js

项目根目录下的.github/workflows/xxx.yml中的自动打包部署工作流完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
name: 构建&分发
on:
push:
branches:
- main # default branch
jobs:
# 构建打包
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
# If your repository depends on submodule, please see: https://github.com/actions/checkout
submodules: recursive
- name: 安装Node
uses: actions/setup-node@v2
with:
node-version: '16'
- name: 安装依赖
run: npm install
- name: 缓存依赖
uses: actions/cache@v2
with:
path: node_modules
key: ${{ runner.OS }}-npm-cache
restore-keys: |
${{ runner.OS }}-npm-cache
- name: 构建
run: npm run build
- name: Create artifact
uses: actions/upload-artifact@v3
with:
name: buildPakage
path: ./public

# 前端包传到服务器覆盖更新
scpToServer:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: buildPakage
path: public #将构件下载到当前工作目录
- name: copy file via ssh key
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
port: 22
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "public/*"
target: '${{ secrets.SERVER_DEPLOY_DIR }}'
rm: true

# 调用腾讯云sdk刷新cdn缓存
ClearCDNCache:
needs: scpToServer
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '16' # 指定 Node.js 版本

- name: Install dependencies
run: npm install tencentcloud-sdk-nodejs

- name: Purge Cache with Tencent SDK
env:
TENCENT_CLOUD_SECRET_ID: ${{ secrets.TENCENT_CLOUD_SECRET_ID }}
TENCENT_CLOUD_SECRET_KEY: ${{ secrets.TENCENT_CLOUD_SECRET_KEY }}
run: |
# 创建一个临时的 JS 文件用于执行腾讯云 API 请求
echo 'const tencentcloud = require("tencentcloud-sdk-nodejs");' > clearCache.js
echo 'const TeoClient = tencentcloud.teo.v20220901.Client;' >> clearCache.js
echo 'const clientConfig = {' >> clearCache.js
echo ' credential: {' >> clearCache.js
echo ' secretId: process.env.TENCENT_CLOUD_SECRET_ID,' >> clearCache.js
echo ' secretKey: process.env.TENCENT_CLOUD_SECRET_KEY,' >> clearCache.js
echo ' },' >> clearCache.js
echo ' region: "ap-chengdu",' >> clearCache.js
echo ' profile: {' >> clearCache.js
echo ' httpProfile: {' >> clearCache.js
echo ' endpoint: "teo.tencentcloudapi.com",' >> clearCache.js
echo ' },' >> clearCache.js
echo ' },' >> clearCache.js
echo '};' >> clearCache.js

echo 'const client = new TeoClient(clientConfig);' >> clearCache.js
echo 'const params = {' >> clearCache.js
echo ' Targets: ["www.yourdomin.com"],' >> clearCache.js
echo ' Type: "purge_host",' >> clearCache.js
echo ' ZoneId: "yourSiteZoneId",' >> clearCache.js
echo '};' >> clearCache.js

echo 'client.CreatePurgeTask(params).then(' >> clearCache.js
echo ' (data) => {' >> clearCache.js
echo ' console.log(data);' >> clearCache.js
echo ' },' >> clearCache.js
echo ' (err) => {' >> clearCache.js
echo ' console.error("error", err);' >> clearCache.js
echo ' }' >> clearCache.js
echo ');' >> clearCache.js

# 运行该脚本
node clearCache.js

题外:

如果不使用腾讯云SDK,也可以直接在bash环境中直接使用curl工具发送请求,笔者最先尝试的就是这个方式,但是中途遇到生成签名的问题难以解决,恰巧又发现了有sdk这个好东西,于是放弃了该思路,有兴趣有时间的同学可以自行研究探索。以下是相关不完整的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 调用 腾讯云API 清除缓存接口
ClearCDNCache:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Generate Signature
id: generate_signature
run: |
# 获取当前时间戳和日期
TIMESTAMP=$(date +%s)
DATE=$(date -u +%Y-%m-%d)

# 设置请求参数
SECRET_ID=${{ secrets.TENCENT_CLOUD_SECRET_ID }}
SECRET_KEY=${{ secrets.TENCENT_CLOUD_SECRET_KEY }}
REGION="ap-chengdu"
SERVICE="teo"

# 创建待签名字符串(示例,请根据腾讯云的具体要求调整)
CANONICAL_REQUEST="POST\n/\n\nhost:teo.tencentcloudapi.com\ncontent-type:application/json\n\nhost;content-type\nUNSIGNED-PAYLOAD"
STRING_TO_SIGN="TC3-HMAC-SHA256\n${TIMESTAMP}\n${DATE}/${REGION}/${SERVICE}/tc3_request\n$(echo -n "${CANONICAL_REQUEST}" | sha256sum | awk '{print $1}')"

# 生成签名密钥
SIGNING_KEY=$(echo -n "${DATE}/${REGION}/${SERVICE}/tc3_request" | openssl dgst -sha256 -hmac "${SECRET_KEY}" -binary | xxd -p)

# 生成最终签名
SIGNATURE=$(echo -n "${STRING_TO_SIGN}" | openssl dgst -sha256 -hmac "${SIGNING_KEY}" | awk '{print $2}')

# 输出环境变量
echo "SIGNATURE=${SIGNATURE}" >> $GITHUB_ENV
echo "TIMESTAMP=${TIMESTAMP}" >> $GITHUB_ENV
echo "DATE=${DATE}" >> $GITHUB_ENV
echo "REGION=${REGION}" >> $GITHUB_ENV

- name: Purge Cache
run: |
# 设置变量
SITE_HOST="yourSiteZoneID"

# 发起请求创建缓存清除任务
curl -X POST https://teo.tencentcloudapi.com/ \
-H "Content-Type: application/json" \
-H "X-TC-Version:2022-09-01" \
-H "X-TC-Action: CreatePurgeTask" \
-H "X-TC-Timestamp: ${{ env.TIMESTAMP }}" \
-H "X-TC-Region: ${{ env.REGION }}" \
-H "Authorization: TC3-HMAC-SHA256 Credential=${{ secrets.TENCENT_CLOUD_SECRET_ID }}/${{ env.DATE }}/${{ env.REGION }}/${{ secrets.SERVICE }}/tc3_request, SignedHeaders=host;content-type, Signature=${{ env.SIGNATURE }}" \
-d "{
\"Targets\": [\"yourDomin\"],
\"Type\": \"purge_host\",
\"ZoneId\": \"${SITE_HOST}\"
}"