腾讯云的COS和CDN产品是天生一对,搭配使用和大幅提高下载速度,降低成本,优化性能。但是其中也存在一个问题,当COS文件更新(重新上传或删除)CDN仍然保存缓存内容,造成与源站不一致,那能否在COS更新的时候自动刷新CDN 的缓存呢?答案是肯定的。我们可以使用腾讯云的另一个款产品SCF(无服务器云函数)来实现。
实现的方法为:
1.创建COS bucket并绑定CDN


2.创建SCF函数和COS操作触发器
我们进入SCF控制台,创建与COS同地域的函数。

↑↑↑创建一个“空白函数”,函数名和运行环境根据自己的业务需要,我们这里起名test_php 运行环境选择PHP 5.6
注:选择的运行环境和后面封装CDN使用的语言环境有关。

↑↑↑创建两个COS触发器,分别是文件上传时触发,文件删除时触发,COS和SCF函数必须为同一地域。
3.实现上传事件解析和刷新CDN功能
添加函数代码:
<?php | |
$gl = 1; | |
function main_handler($event, $context) { | |
$eve = json_decode(json_encode($event,JSON_FORCE_OBJECT),true); | |
$usr_url=strval($eve["Records"][0]["cos"]["cosObject"]["url"]); | |
//截取object部分 | |
$object=substr($usr_url,strpos($usr_url,"/",8)); | |
/*需要填写您的密钥,可从 https://console.cloud.tencent.com/capi 获取 SecretId 及 $secretKey*/ | |
$secretKey='这里替换您的secretKey'; | |
$secretId='这里替换您的secretId'; | |
$action='RefreshCdnUrl'; | |
$HttpUrl="cdn.api.qcloud.com"; | |
/*除非有特殊说明,如MultipartUploadVodFile,其它接口都支持GET及POST*/ | |
$HttpMethod="GET"; | |
/*是否https协议,大部分接口都必须为https,只有少部分接口除外(如MultipartUploadVodFile)*/ | |
$isHttps =true; | |
$nurl="http://这里替换成您的CDN域名".$object; // 示例:$nurl="http://abc.com".$object; | |
//print_r($nurl); | |
/*下面这五个参数为所有接口的 公共参数;对于某些接口没有地域概念,则不用传递Region(如DescribeDeals)*/ | |
$COMMON_PARAMS = array( | |
'Nonce' => rand(), | |
'Timestamp' =>time(NULL), | |
'Action' =>$action, | |
'SecretId' => $secretId, | |
'SignatureMethod' => 'HmacSHA256', | |
'urls.0' => $nurl | |
); | |
$PRIVATE_PARAMS = array(); | |
//**********执行CDN刷新URL操作**********/ | |
CreateRequest($HttpUrl,$HttpMethod,$COMMON_PARAMS,$secretKey, $PRIVATE_PARAMS, $isHttps); | |
return "RefreshCdnUrl OK"; | |
} | |
/***************CDN API调用方法***************/ | |
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('sha256', $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)); | |
} | |
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, true); | |
if ($isHttps === true) { | |
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); | |
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); | |
} | |
$result = curl_exec($ch); | |
return $result; | |
} | |
?> |
↑↑↑上面内容为解析COS触发事件并刷新CDN URL的代码,注意代码中三个替换标识,需要更换成您自己的资源配置。
4.验证效果
↑↑↑进入COS控制台上传一个文件对象并且删除一个已存在文件对象
↑↑↑SCF会触发并生成两个执行日志。注:如需调试,可在函数中增加输出语句。
↑↑↑访问CDN控制台的缓存刷新–操作记录,可以看到我们上传和删除的资源均被刷新了,验证成功。
后记:在上面的实践中,我们实现了COS上传和删除文件对象时自动刷新CDN URL的功能,当然SCF产品功能并不止于此,您也可以通过代码来实现刷新后的预热功能,甚至调用CVM等其他业务服务器的功能,灵活组合,搭配使用,更多操作,等您来用。
正文完