【玩转 EdgeOne】加速COS静态网站并实现动态刷新

本文最后更新于:2023年10月24日 晚上

导言

SCF遇到的问题

腾讯云有一款Serverless Framework产品,可以从本地把网站等框架快速部署到腾讯云产品上而无需复杂的服务器配置。

但是截止至目前,腾讯云scf支持接入的加速只有cdn,暂未支持edgeone,如果直接在serverless.yml里面填入在edgeone托管的网站,则会报错,该域名未接入CDN

CRA遇到的问题

由于笔者开发使用的是Create-React-App的网站框架,每次部署都需要刷新缓存否则就会造成资源找不到的问题。由于scf建站可以实现自动刷新CDN缓存,但是没办法自动刷新edgeone缓存,即使使用云函数COS触发,也只有CDN的方案,至于EO,只能通过API+SCF的方案来解决。

原理

触发

因为scf部署网站会更新cos内容,而scf有一个cos触发器,当cos内容改变时会触发函数执行,此时我们就可以利用这种方式来实现动态更新。

请在此添加图片描述

API

腾讯云EdgeOne(TEO)有一个API接口 CreatePurgeTask,即为 创建清除缓存任务,可以在 ApiExplorer 找到调用该API的文档和方式

实现

要求

  • 域名必须已经接入eo
  • 后端必须是腾讯云cos
  • 已开通COS,SCF,TEO等服务

SCF在使用过程中会产生费用(无资源包的会产生最低消费),请务必了解后再使用!

API使用

ApiExplorer 找到调用该API的文档和方式

参数说明

需要传入的参数如下:

  • ZoneId 站点ID,可在 EdgeOne控制台-站点列表 找到
    请在此添加图片描述
  • Type 清除缓存的类型,请根据需要,查看产品文档来选择,笔者的CRA是整个域名的更新,所以使用 purge_host
  • Method 节点缓存清除方法,使用刷新变更资源的方式 invalidate
  • Targets 刷新的目标,根据 Type 传入的字段选择。这里使用的是 purge_host,所以传入刷新的hostname,例如 www.arsrna.com。当然我们这里不一定只给一个域名进行刷新,可以传入多个hostname,以数组的方式传入

SCF侧接入

函数代码

在APIExplorer代码生成处,可以获得SDK运行所需要的代码,这里以nodejs为例,其他语言方法一样。

请在此添加图片描述

进入SCF控制台,单击新建函数,选择 从头开始,使用事件函数。

运行环境根据APIExplorer生成代码的语言选择

请在此添加图片描述

地域尽量选择跟腾讯云TEO SDK相同的地域,在API Explorer的参数 Region可以查看

请在此添加图片描述

剩下的参数暂时不需要设置,单击完成

进入函数控制台,编辑函数代码

根据各语言的要求,安装对应依赖,引入依赖,新版函数编辑器可以右键文件夹,点击在终端中打开,即可调出终端

请在此添加图片描述

请在此添加图片描述

根据各语言要求,修改函数代码

代码demo

以下为nodejs的demo,可按需修改

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
const tencentcloud = require("tencentcloud-sdk-nodejs-teo");
const TeoClient = tencentcloud.teo.v20220901.Client;

exports.main_handler = async (event, context) => {
const {secretId,secretKey}=process.env;
// 已使用环境变量的方式,不放在代码,建议使用最小权限存储,参见https://cloud.tencent.com/document/product/1278/85305
const clientConfig = {
credential: {
secretId,
secretKey,
},
region: "ap-guangzhou",
profile: {
httpProfile: {
endpoint: "teo.tencentcloudapi.com",
},
},
};
const client = new TeoClient(clientConfig);
const params = {
"ZoneId": "zone-xxxxxxxxxx", //ZoneId,可在控制台找到
"Type": "purge_host",
"Method": "invalidate",
"Targets": [
"arsrna.cn", //传入域名,可传入多个
"www.arsrna.cn"
]
};
return new Promise((resolve,reject)=>{
client.CreatePurgeTask(params).then(
(data) => {
resolve(data);
},
(err) => {
reject(JSON.stringify(err));
}
);
})
};

在控制台上单击测试,查看函数运行结果

请在此添加图片描述

1
2
3
4
5
{
"RequestId":"3bcb9c24-c628-4506-b91f-bad40ae6daf4",
"FailedList":[],
"JobId":"2p0bf4pucgks"
}

如果 FailedList为空,证明运行成功,可以前往EO控制台查看效果

请在此添加图片描述

COS接入

在刚刚函数的控制台处切换到触发器管理,新建一个COS触发器,选择对应存储桶(eo源站设置的存储桶)。事件类型选全部创建并立即启用。

请在此添加图片描述

提交后即可生效,此时往cos增删改文件都会触发刷新缓存的命令。

scf部署网站CLI命令为 scf deploy,详细可以查阅serverless framework的说明

通用化

我们并不希望一个存储桶一个函数,不仅不方便管理,还会造成多余的资源占用

请在此添加图片描述

此时可以根据更改的cos桶来进行判断刷新的网站,在函数里面加入映射的关系。

如上图所示,以nodejs代码为例,可以写成

1
2
3
4
5
6
7
function getEOHosts(bucketName){
const mapping={
'test-a':['a.com','b.com','c.com'],
'test-b':['d.com','e.com','f.com','g.com']
}
return mapping[bucketName];
}

cos触发器会向函数发送一个json请求,可以取到对应bucket name

请在此添加图片描述

上述创建的事件函数里,bucket名称在路径 event.Records[0].cos.cosBucket.name下,我们上传一个文件,就可以看到触发了。

请在此添加图片描述

再根据上面的映射,改造代码:

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
const tencentcloud = require("tencentcloud-sdk-nodejs-teo");
const TeoClient = tencentcloud.teo.v20220901.Client;

function getEOHosts(bucketName){
const mapping={
'test-a':['a.com','b.com','c.com'],
'test-b':['d.com','e.com','f.com','g.com']
}
return mapping[bucketName];
}

exports.main_handler = async (event, context) => {
const bucketName=event.Records[0].cos.cosBucket.name;
const {secretId,secretKey}=process.env;
const clientConfig = {
credential: {
secretId,
secretKey,
},
region: "ap-guangzhou",
profile: {
httpProfile: {
endpoint: "teo.tencentcloudapi.com",
},
},
};

// 实例化要请求产品的client对象,clientProfile是可选的
const client = new TeoClient(clientConfig);
const params = {
"ZoneId": "zone-xxxxxxx",
"Type": "purge_host",
"Method": "invalidate",
"Targets": getEOHosts(bucketName)
};
return new Promise((resolve,reject)=>{
client.CreatePurgeTask(params).then(
(data) => {
resolve(data);
},
(err) => {
reject(JSON.stringify(err));
}
);
})
};

在scf触发器管理里,创建多个cos触发器,即可实现一个函数,多cos,单eo自动更新

当然,此时只能实现单eo自动更新,如果要实现多eo站点更新,可以在映射里面加入多个参数,这里不再赘述,各语言实现的方式不一样。

Ar-Sr-Na原创,未经允许禁止转载

代码仅做参考,由此造成的一切问题与作者无关。


【玩转 EdgeOne】加速COS静态网站并实现动态刷新
https://www.arirs.cn/posts/2348693/
作者
Ar-Sr-Na
发布于
2023年10月24日
许可协议