腾讯云的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等其他业务服务器的功能,灵活组合,搭配使用,更多操作,等您来用。
正文完