摘要生成中...
AI 摘要
Hunyuan-lite
本文已收录至 Butterfly 主题美化教程

使用了 CDN 或其他边缘加速产品加速源站的小伙伴可能会遇到一个问题,那就是每次发布博客到服务器后,都需要手动在控制台进行节点的缓存刷新,很是麻烦。这里我介绍几种刷新边缘结点缓存的方法,对于 Hexo 博客,将着重介绍通过脚本的思路实现一键发布的具体流程。

腾讯云对象存储的 CDN 刷新

首先介绍官方方案。点击存储桶后可以找到 CDN 缓存刷新函数,这是一项收费服务。有兴趣的小伙伴可以试一试。

image.png

Hexo 自写 JavaScript 脚本并利用钩子实现

思路(package.json 的编写)

在接触 Hexo 博客建站的时候,你一定会知道 Hexo 三连:

1
2
3
hexo clean && hexo g && hexo d
# 当然可以简写成
hexo clean && hexo d -g

命令含义参考:指令 | Hexo

上面的命令可以写进 [blog_root]/package.jsonscripts 中,如:

1
2
3
4
"scripts": {
"publish": "hexo clean && hexo d -g",
"start": "hexo clean && hexo g && hexo s"
},

这样每次部署我们只需要运行 npm run publish 即可完成连击。

在完成博客部署连击后,我们可以再执行一个脚本刷新腾讯云 CDN 缓存。我打算写一个 JavaScript 脚本 auto_flush_cdn.js 用 Node 运行(搭有 Hexo 的总会装有 Node.js 的吧)。

这样我们的部署脚本就会是这样:

1
2
3
"scripts": {
"publish": "hexo clean && hexo d -g && node .\\auto_flush_cdn.js",
},

或者利用钩子:

1
2
3
4
"scripts": {
"publish": "hexo clean && hexo d -g",
"postpublish": "node .\\auto_flush_cdn.js",
},

触发流程解决好后,下一个任务就是 auto_flush_cdn.js 的编写。

使用腾讯云 SDK 进行开发

登录腾讯云后,打开云产品 ->云 API:

image-20230501153225264

我们要使用腾讯云 SDK,需要先安装依赖:

依赖下载dfsdf

这里我就安装在博客目录了:博客下新建终端运行命令 npm install tencentcloud-sdk-nodejs-cdn --save

「找不到模块」的解决方案

实践中遇到找不到模块的问题,安装好依赖后记得重启终端、VSCode 甚至电脑。如果不行请另外搜索解决方案。

然后找到对应的 API,按照平台指示的说明填写好参数,充分利用其诊断工具进行在线调试。(一般不会出什么问题)

线上尝试接口dfdff

没有问题的话我们就可以把平台代码复制下来了,在代码中改改 API ID 和 API KEY 参数即可。

密钥安全性提示

此处 API ID 和 API KEY 参数填写仅供演示。为了安全起见,建议不要在代码中写入任何的密匙,应将密钥放置在环境变量中。详见:站内文章系统环境变量的设置与获取

运行一下我们的脚本文件尝试一下:

成功ddf

没有返回错误信息,看了看控制台确实进行了刷新。如果出现问题,可以把 RequestId 粘贴到 API Doctor(使用诊断) - 云 API - 控制台 (tencent.com) 进行诊断。

附控制台看刷新纪录的方法,打开内容分发网络找刷新预热的操作记录:

查看有没有刷新成功6546

如果你使用的边缘产品是腾讯云的 EdgeOne,操作也大差不差:API Explorer - 云 API - 控制台

脚本

注意系统中提前配置好 TENCENT_API_SECRETIDTENCENT_API_SECRETKEY 环境变量。

一般刷新网站首页和 RSS 订阅页即可。

最后的脚本文件文件:

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
// Depends on tencentcloud-sdk-nodejs version 4.0.3 or higher
const tencentcloud = require("tencentcloud-sdk-nodejs-cdn");

const CdnClient = tencentcloud.cdn.v20180606.Client;

var secretId = process.env.TENCENT_API_SECRETID;
var secretKey = process.env.TENCENT_API_SECRETKEY;

// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
const clientConfig = {
credential: {
secretId: secretId,
secretKey: secretKey,
},
region: "",
profile: {
httpProfile: {
endpoint: "cdn.tencentcloudapi.com",
},
},
};

// 实例化要请求产品的client对象,clientProfile是可选的
const client = new CdnClient(clientConfig);
const params = {
"Paths": [
/* 替换成你的网址 */
"https://uuanqin.top",
"https://www.uuanqin.top",
"https://blog.uuanqin.top/atom.xml"
],
"FlushType": "delete"
};
client.PurgePathCache(params).then(
(data) => {
console.log(data);
},
(err) => {
console.error("error", err);
}
);

WordPress 解决方案

functions.php 下添加自动刷新腾讯云控制台 CDN 缓存的操作。

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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/* 需要填写你的密钥,访问 https://console.qcloud.com/capi 获取 SecretId 及 $secretKey */
$secretKey = '填写你的密钥';
$secretId = '填写你的密钥';

//更新或发布文章清理本文和首页CDN缓存
add_action('publish_post', 'Clean_By_Publish', 0);

//提交评论更新本文CDN缓存
add_action('comment_post', 'Clean_By_Comments',0);

//评论被审核更新本文CDN缓存
add_action('comment_unapproved_to_approved', 'Clean_By_Approved',0);

//发布文章更新CDN缓存函数
function Clean_By_Publish($post_ID){
global $secretKey,$secretId;
$url = get_permalink($post_ID);
$action='RefreshCdnUrl';
/*要清理的页面,默认包含首页和文章页面,需要清理其他页面请自行发挥*/
$PRIVATE_PARAMS = array(
'urls.0' => home_url(),
'urls.1' => $url ,
);
$HttpUrl="cdn.api.qcloud.com";
/*除非有特殊说明,如MultipartUploadVodFile,其它接口都支持GET及POST*/
$HttpMethod="POST";
/*是否https协议,大部分接口都必须为https,只有少部分接口除外(如MultipartUploadVodFile)*/
$isHttps =true;
/*下面这五个参数为所有接口的 公共参数;对于某些接口没有地域概念,则不用传递Region(如DescribeDeals)*/
$COMMON_PARAMS = array(
'Nonce' => rand(),
'Timestamp' =>time(NULL),
'Action' =>$action,
'SecretId' => $secretId,
);
/***********************************************************************************/
CreateRequest($HttpUrl,$HttpMethod,$COMMON_PARAMS,$secretKey, $PRIVATE_PARAMS, $isHttps);
}

//提交评论清理文章CDN函数
function Clean_By_Comments($comment_id)
{
global $secretKey,$secretId;
$comment = get_comment($comment_id);
$url = get_permalink($comment->comment_post_ID);
$action='RefreshCdnUrl';
/*参数*/
$PRIVATE_PARAMS = array(
'urls.0' => $url,
);
$HttpUrl="cdn.api.qcloud.com";
/*除非有特殊说明,如MultipartUploadVodFile,其它接口都支持GET及POST*/
$HttpMethod="POST";
/*是否https协议,大部分接口都必须为https,只有少部分接口除外(如MultipartUploadVodFile)*/
$isHttps =true;
/*下面这五个参数为所有接口的 公共参数;对于某些接口没有地域概念,则不用传递Region(如DescribeDeals)*/
$COMMON_PARAMS = array(
'Nonce' => rand(),
'Timestamp' =>time(NULL),
'Action' =>$action,
'SecretId' => $secretId,
);
/***********************************************************************************/
CreateRequest($HttpUrl,$HttpMethod,$COMMON_PARAMS,$secretKey, $PRIVATE_PARAMS, $isHttps);
}

//评论被审核清理CDN缓存函数
function Clean_By_Approved($comment)
{
global $secretKey,$secretId;
$url = get_permalink($comment->comment_post_ID);
$action='RefreshCdnUrl';
/*参数*/
$PRIVATE_PARAMS = array(
'urls.0' => $url,
);
$HttpUrl="cdn.api.qcloud.com";
/*除非有特殊说明,如MultipartUploadVodFile,其它接口都支持GET及POST*/
$HttpMethod="POST";
/*是否https协议,大部分接口都必须为https,只有少部分接口除外(如MultipartUploadVodFile)*/
$isHttps =true;
/*下面这五个参数为所有接口的 公共参数;对于某些接口没有地域概念,则不用传递Region(如DescribeDeals)*/
$COMMON_PARAMS = array(
'Nonce' => rand(),
'Timestamp' =>time(NULL),
'Action' =>$action,
'SecretId' => $secretId,
);
/***********************************************************************************/
CreateRequest($HttpUrl,$HttpMethod,$COMMON_PARAMS,$secretKey, $PRIVATE_PARAMS, $isHttps);
}

//请求主函数,无需改动
function CreateRequest($HttpUrl,$HttpMethod,$COMMON_PARAMS,$secretKey, $PRIVATE_PARAMS, $isHttps)
{
$FullHttpUrl = $HttpUrl."/v2/index.php";
/***************对请求参数 按参数名 做字典序升序排列,注意此排序区分大小写*************/
$ReqParaArray = array_merge($COMMON_PARAMS, $PRIVATE_PARAMS);
ksort($ReqParaArray);
/**********************************生成签名原文**********************************
* 将 请求方法, URI地址,及排序好的请求参数 按照下面格式 拼接在一起, 生成签名原文,此请求中的原文为
* GETcvm.api.qcloud.com/v2/index.php?Action=DescribeInstances&Nonce=345122&Region=gz
* &SecretId=AKIDz8krbsJ5yKBZQ ·1pn74WFkmLPx3gnPhESA&Timestamp=1408704141
* &instanceIds.0=qcvm12345&instanceIds.1=qcvm56789
* ****************************************************************************/
$SigTxt = $HttpMethod.$FullHttpUrl."?";
$isFirst = true;
foreach ($ReqParaArray as $key => $value)
{
if (!$isFirst)
{
$SigTxt = $SigTxt."&";
}
$isFirst= false;
/*拼接签名原文时,如果参数名称中携带_,需要替换成.*/
if(strpos($key, '_'))
{
$key = str_replace('_', '.', $key);
}
$SigTxt=$SigTxt.$key."=".$value;
}
/*********************根据签名原文字符串 $SigTxt,生成签名 Signature******************/
$Signature = base64_encode(hash_hmac('sha1', $SigTxt, $secretKey, true));
/***************拼接请求串,对于请求参数及签名,需要进行urlencode编码********************/
$Req = "Signature=".urlencode($Signature);
foreach ($ReqParaArray as $key => $value)
{
$Req=$Req."&".$key."=".urlencode($value);
}
/*********************************发送请求********************************/
if($HttpMethod === 'GET')
{
if($isHttps === true)
{
$Req="https://".$FullHttpUrl."?".$Req;
}
else
{
$Req="http://".$FullHttpUrl."?".$Req;
}
$Rsp = file_get_contents($Req);
}
else
{
if($isHttps === true)
{
$Rsp= SendPost("https://".$FullHttpUrl,$Req,$isHttps);
}
else
{
$Rsp= SendPost("http://".$FullHttpUrl,$Req,$isHttps);
}
}
//var_export(json_decode($Rsp,true));
return json_decode($Rsp,true);
}
function SendPost($FullHttpUrl, $Req, $isHttps)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $Req);
curl_setopt($ch, CURLOPT_URL, $FullHttpUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 1 );
if ($isHttps === true) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
$result = curl_exec($ch);
return $result;
}

本文参考