直达最佳实践:【 Serverless架构实现CDN预热最佳实践】
最佳实践频道:【 最佳实践频道】
这里有丰富的企业上云最佳实践,从典型场景入门,提供一系列项目实践方案,降低企业上云门槛的同时满足您的需求!
为什么要预热
首先,什么是CDN预热呢?
CDN预热是指源站主动将对应的资源缓存到CDN节点,当您首次请求资源时,即可直接从CDN节点获取到最新的资源,无需再回源站获取,从而降低访问延时,提升访问体验。例如,在游戏行业中,某个热门游戏首发时,会有大量玩家等待开服,第一时间下载客户端。通常游戏客户端都比较大,如果没有预热,最先体验游戏的玩家下载时,CDN中还没有缓存,就会先回源到源站获取游戏客户端,这样下载速度往往会很慢,而且源站的主机CPU和带宽在短时间内被大量用户访问,也会占用大量资源,通常源站的带宽成本比CDN要高,不但影响用户体验也增加带宽成本。如果有了CDN预热,在游戏开服前把游戏安装包提前通过预热的方式推送到各个CDN节点,最先开始下载的玩家都能直接从CDN缓存中快速获取安装包,大大提升下载体验。
举个“栗”子
接下来以一个山东游戏用户为例(以下数据为构造数据),在无CDN加速的情况下,直接访问源站,大概耗时50ms。在使用CDN,但CDN未命中的情况下,通过访问山东L1到北京L2到上海机房,整体延时大约40ms,比直接访问减少10ms。再看下,如果直接命中CDN缓存,则只需要5ms,大大降低了访问延时,同时直接命中CDN缓存访问链路也极大缩短了,链路的访问质量显著提升。可见如果能快速命中缓存,对用户体验的提升非常明显,而CDN预热是一种非常有效的手段。
Serverless架构有什么好处
- 按照CNCF对Serverless计算的定义,Serverless架构是指采用FaaS(函数即服务)和BaaS(后端服务)服务来解决问题的一种设计。这个架构免去了服务器运维,具有更高扩展性和安全性,成本也更低。
- 在CDN预热方面,我们使用serverless架构,实现CDN预热的自动化和智能化,原先需要开发大量的代码、部署多个服务来实现CDN预热,现在完全无需管理服务器,比如操作系统的安全补丁、故障升级和高可用都无需用户考虑了。这种架构下资源变成了弹性扩展,不需做容量规划,按需付费也降低使用成本。在安全性方面,用户看不到服务器,也不需要通过SSH登录,DDoS攻击也交给云厂商解决了。
- 在架构方面变得更简单了,用户自动化提交预热脚本后,在MNS里面形成消息队列,消息队列自动化触发函数计算,对需要预热的资源进行预热,整个过程完全以运维自动化的方式执行。
Serverless实现CDN预热的思路
- 首先,我们要寻找什么适合预热,前面介绍过热点资源大文件需要预热,另外如果是小文件,访问热度非常高的内容,一出来就会被访问,而且回源时间也很短,这种资源往往本身命中就很高了,所以不需要预热。另一类非常冷的资源,基本没有用户访问,从节约成本的角度,这种资源做预热收益率太低也可以不考虑。所以访问热度介于两者之间的,或者有区域性质的内容,比如短视频平台的本地视频、新闻内容APP的本地新闻,直播平台的附近直播,这些资源传播需要一定时间,可以通过预热提前推送到CDN L2节点,加速资源访问效率。因此在函数计算中,我们可以编写函数通过函数工作流定时调度执性函数去找出这样的资源,添加到预热URL列表中。
- 其次,还要寻找什么时间适合预热,我们需要分析CDN的计费模式,如大客户一般采用95峰值计费的方式,即以5分钟记录一个带宽点,全月的值从大到小排列,去除前5%的峰值,取第95%的这个点作为实际计费带宽。为了更好利用带宽,预热的时间最好选择在波谷位置,这样做到削峰填谷,降低带宽使用成本。在Serverless架构下,我们使用函数计算编写业务逻辑,可以有效控制预热时间。
- 当我们对预热的内容和时间有了精准的控制后,自动化执行脚本,把需要预热的URL推送到MNS作为缓存队列,这样也避免了预热URL过多的情况下,分批提交导致预热效率过低的问题。消息队列自动化触发函数计算执行预热任务。函数计算中的执行代码参考如下:
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkcdn.request.v20180510.RefreshObjectCachesRequest import RefreshObjectCachesRequest
from aliyunsdkcdn.request.v20180510.PushObjectCacheRequest import PushObjectCacheRequest
from aliyunsdkcdn.request.v20180510.DescribeRefreshTasksRequest import DescribeRefreshTasksRequest
from aliyunsdkcdn.request.v20180510.DescribeRefreshQuotaRequest import DescribeRefreshQuotaRequest
def handler(event, context):
id = 'LTA*********nRkRaYb7'
secret = 'YJuNY*************rdeKLnl'
client = AcsClient(id, secret, 'cn-shenzhen')
obj = json.loads(event)
doRefresh(obj['urls'], obj['type'], obj['objectType'], obj['area'], client)
return 'hello world'
def doRefresh(lists,types,objectType,area,client):
try:
if types == 'clear':
taskID = 'RefreshTaskId'
request = RefreshObjectCachesRequest()
if objectType:
request.set_ObjectType(objectType)
elif types == 'push':
taskID = 'PushTaskId'
request = PushObjectCacheRequest()
if area:
request.set_Area(area)
taskreq = DescribeRefreshTasksRequest()
request.set_accept_format('json')
request.set_ObjectPath(lists)
response = json.loads(client.do_action_with_exception(request))
print(response)
while True:
count = 0
taskreq.set_accept_format('json')
taskreq.set_TaskId(int(response[taskID]))
taskresp = json.loads(client.do_action_with_exception(taskreq))
print("[" + response[taskID] + "]" + "is doing... ...")
for t in taskresp['Tasks']['CDNTask']:
if t['Status'] != 'Complete':
count += 1
if count == 0:
break
else:
continue
time.sleep(5)
except Exception as e:
sys.exit("[Error]" + str(e))
总结
CDN预热场景非常适合Serverless架构实现,比如内容和预热时间选择的自动化、消息队列的缓存及监听、自动化触发函数执行URL预热等有效帮助客户业务提升缓存命中率、提高运维效率、降低带宽使用成本,提升用户体验。
本文篇幅有限,更多的具体实现及实操参考最佳实践:Serverless架构实现CDN预热