在把前端静态资源或者接口网关配置通过流水线部署到对象存储与源站之后,边缘节点的旧文件可能仍然被用户命中。腾讯云CDN提供了基于API的缓存刷新能力,只要在工程流水线中增加一个后置步骤,就能在代码发布完成时自动让指定URL或目录失效。这样做比人工登录控制台操作更可靠,也能和回滚脚本形成对称能力。

为什么要把缓存刷新放进CI/CD而不是手动处理
很多团队在发布前端包之后,习惯由运维同学打开腾讯云控制台,手动粘贴需要刷新的路径并提交。这种做法在小项目里问题不大,但当微服务数量变多、每日发布频次上升到几十次时,漏刷和错刷就成了常态。用户侧表现为白屏、按钮无响应或者读到了旧接口结构,而排查时往往要花很长时间才定位到是CDN边缘缓存未更新。
将刷新动作编写为流水线的一个阶段,本质上是把缓存生命周期纳入版本管理。每一次git tag或者merge request合入主干,都会触发同一套刷新逻辑,执行结果也会留在流水线日志里方便审计。如果发布失败需要回退,可以在同一个job中先刷新旧版本路径,保证用户无论命中哪一层都不会出现资源错配。
从成本角度看,腾讯云CDN的URL刷新和目录刷新都有每日配额限制。自动化脚本可以统一计算本次发布实际改动的文件清单,只刷新受影响路径,而不是每次全站目录刷新,这样既省配额也更快生效。结合对象存储的上传清单或者webpack的asset manifest,能做到精确到单个文件的失效。
在GitLab Runner中调用腾讯云SDK刷新缓存
GitLab CI的配置文件写在仓库根目录的.gitlab-ci.yml中。我们可以在build阶段之后增加一个invalidate阶段,使用官方提供的Python SDK(tencentcloud-sdk-python)来完成调用。为了保证密钥安全,应当把SecretId和SecretKey配置为CI/CD Variables,而不是硬编码在脚本里。
下面这段Python代码演示了如何读取环境变量并调用CDN的PurgeUrlsCache接口。注意在pre代码块中,所有的尖括号都已经做了转义处理,可以直接复制到文件使用。脚本会先收集本次发布生成的文件列表,再批量提交刷新。
import os
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.cdn.v20180606 import cdn_client, models
def purge_urls(urls):
try:
cred = credential.Credential(
os.environ.get('TENCENT_SECRET_ID'),
os.environ.get('TENCENT_SECRET_KEY')
)
client = cdn_client.CdnClient(cred, 'ap-guangzhou')
req = models.PurgeUrlsCacheRequest()
req.Urls = urls
resp = client.PurgeUrlsCache(req)
print('refresh task id:', resp.TaskId)
except TencentCloudSDKException as e:
print('purge failed:', e)
raise
if __name__ == '__main__':
changed_files = os.environ.get('CHANGED_FILES', '').split(',')
url_list = ['https://cdn.ippipp.com/' + f for f in changed_files if f]
if url_list:
purge_urls(url_list)
在实际工程里,CHANGED_FILES可以由前面的构建步骤通过git diff-tree或者比对对象存储清单得到。如果一次发布的文件超过腾讯云单次接口上限(目前URL刷新单次最多支持1000条),需要在脚本里做分片循环提交,并对每个分片检查返回状态。
另一个容易忽略的点是网络出口。GitLab Runner如果跑在自建机房,需要确认能访问腾讯云公网API域名。若使用私有Runner且限制出网,可以在VPC内通过 NAT 网关放通cdn.api.qcloud.com相关域名,或者使用腾讯云内网API接入点降低延迟。
GitHub Actions方案与失败重试设计
对于托管在GitHub的仓库,可以使用官方的ubuntu-latest运行器,配合一个独立的job来刷新缓存。和GitLab类似,密钥放在仓库Settings的Secrets中,通过${{ secrets.TENCENT_SECRET_ID }}注入。下面给出一个工作流片段,它在deploy之后运行。
name: frontend-cdn-purge
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: upload to cos
run: bash scripts/upload.sh
purge:
needs: deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: setup python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: install sdk
run: pip install tencentcloud-sdk-python
- name: run purge script
env:
TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
run: python scripts/purge_cdn.py
自动化刷新最怕的是接口偶发限流或网络抖动导致流水线变红。建议在脚本中加入指数退避重试:第一次失败等待两秒,第二次四秒,最多三次。腾讯云对刷新接口有每秒请求数约束,并发提交多个分片时可以用信号量控制每秒不超过五条,避免触发风控。
如果刷新任务返回的状态不是即时生效,而是进入了队列,流水线不应阻塞太久。可以设计为提交后轮询TaskId状态,超时时间设为三分钟,超过则认为成功(因为配额内的刷新通常会在五分钟内完成)。这样既不耽误发布节奏,也能在日志里留下任务编号供后续追踪。
最后要提醒,目录刷新和URL刷新语义不同。目录刷新会让该路径下所有资源失效,适合整包替换的场景;URL刷新更精准,适合只改了部分文件的情况。在CI/CD里最好根据构建产物差异动态选择,而不是无脑刷目录,才能既快又省。