前言

之前有一篇文章就是写了钉钉获取朋友圈执行日志的文章,然后我就在想:我的博客是静态网站,每次需要去刷新CDN,我可不可以去实现一个提交代码后就自动刷新CDN的问题

想法

我一开始的想法是:部署成功后就发生消息给钉钉机器人 然后钉钉机器人收到消息就自动去刷新CDN。但是由于限制,导致我没有去实现。后面看到飞书的,然后发现它的自定义机器人一样有限制。所以我就改成了去监控CDN的使用情况。效果图如下

218715c7-c8d1-4fe1-8596-2f072558d154

获取自定义机器人

在群主中选择设置
d4394b58-ae63-41f7-881f-204f77bd5a5c (1)

在右侧 设置 界面,点击 群机器人

99c87845-4b18-4bc7-aca9-e1dab9bd3901

  1. 在 群机器人 界面点击 添加机器人。
  2. 在 添加机器人 对话框,找到并点击 自定义机器人

fbb297e1-db41-40fb-b4f0-349562240457

自定义机器人头像、昵称、描述 并点击添加

202410169hajx

获取到机器人的webhook地址 保存好webhook 和 签名密钥 并点击 完成

这里要选择签名校验

a43fc7f2-2f44-4c68-ad3a-797524bca0c4

获取腾讯CDN

开发 需要先下载腾讯SDK库

pip install -i https://mirrors.tencent.com/pypi/simple/ --upgrade tencentcloud-sdk-python

这里需要提供 腾讯云API密钥边缘加速CDN的ID

def get_Edgeone():
try:
cred = credential.Credential("密钥", "密钥")
httpProfile = HttpProfile()
httpProfile.endpoint = "teo.tencentcloudapi.com"
clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
client = teo_client.TeoClient(cred, "", clientProfile)
current_datetime = datetime.utcnow()

start_of_day = current_datetime.replace(hour=0, minute=0, second=0, microsecond=0)

end_of_day = current_datetime.replace(hour=23, minute=59, second=59, microsecond=999999)

start_of_day_iso = start_of_day.strftime('%Y-%m-%dT%H:%M:%SZ')
end_of_day_iso = end_of_day.strftime('%Y-%m-%dT%H:%M:%SZ')
req = models.DescribeTimingL7AnalysisDataRequest()
params = {
"StartTime": start_of_day_iso,
"EndTime": end_of_day_iso,
"MetricNames": ["l7Flow_outFlux", "l7Flow_inFlux", "l7Flow_request"],
"ZoneIds": ["CDN ID"],
"Interval": "day",
"Area": "mainland"
}
req.from_json_string(json.dumps(params))

# 返回的resp是一个DescribeTimingL7AnalysisDataResponse的实例,与请求对象对应
resp = client.DescribeTimingL7AnalysisData(req)
# 输出json格式的字符串回包
print(resp.to_json_string())
data = json.loads(resp.to_json_string())
l7Flow_request_value = None

for item in data["Data"][0]["TypeValue"]:
if item["MetricName"] == "l7Flow_request":
l7Flow_request_value = item["Sum"]
break

total_influx = 0
total_outflux = 0

for item in data["Data"][0]["TypeValue"]:
if item["MetricName"] == "l7Flow_inFlux":
total_influx += item["Sum"]
elif item["MetricName"] == "l7Flow_outFlux":
total_outflux += item["Sum"]

total_influx_megabytes = round(total_influx / (1024 * 1024), 2)
total_outflux_megabytes = round(total_outflux / (1024 * 1024), 2)

print("访问请求:", l7Flow_request_value)
print("请求流量:", total_influx_megabytes)
print("响应流量:", total_outflux_megabytes)

return l7Flow_request_value, total_influx_megabytes, total_outflux_megabytes
except TencentCloudSDKException as err:
print(err)

填入腾讯云密钥

cred = credential.Credential("密钥", "密钥")

填入CDN的ID 这里只需要修改 ZoneIds

params = {
"StartTime": start_of_day_iso,
"EndTime": end_of_day_iso,
"MetricNames": ["l7Flow_outFlux", "l7Flow_inFlux", "l7Flow_request"],
"ZoneIds": ["CDN ID"],
"Interval": "day",
"Area": "mainland"
}

获取多吉云CDN信息

需要获取到多吉云 access_keysecret_key

# 多吉云API
def dogecloud_api(api_path, data={}, json_mode=False):
access_key = 'xxxxx'
secret_key = 'xxxx'

body = ''
mime = ''
if json_mode:
body = json.dumps(data)
mime = 'application/json'
else:
body = urllib.parse.urlencode(data) # Python 2 可以直接用 urllib.urlencode
mime = 'application/x-www-form-urlencoded'
sign_str = api_path + "\n" + body
signed_data = hmac.new(secret_key.encode('utf-8'), sign_str.encode('utf-8'), sha1)
sign = signed_data.digest().hex()
authorization = 'TOKEN ' + access_key + ':' + sign
response = requests.post('https://api.dogecloud.com' + api_path, data=body, headers={
'Authorization': authorization,
'Content-Type': mime
})
return response.json()


# 获取流量数据
def Get_traffic():
current_time = datetime.now()
formatted_date = current_time.strftime("%Y-%m-%d")
api = dogecloud_api('/cdn/stat/traffic.json', {
'rtype': 'path',
'start_date': formatted_date,
'end_date': formatted_date,
'granularity': 'day',
'area': 'china',
'domains': 'test.com'
})
if api['code'] == 200:
data_result = api['data']['result']

if data_result:
data_values = data_result[0]['data']
data_values_megabytes = [value / (1024 * 1024) for value in data_values]
print("Data values in Megabytes:", data_values_megabytes)
traffres = [round(value, 2) for value in data_values_megabytes]
return traffres
else:
print("No data available.")
else:
print("API failed: " + api['msg'])


# 获取请求数
def Get_reuestcount():
current_time = datetime.now()
formatted_date = current_time.strftime("%Y-%m-%d")
api = dogecloud_api('/cdn/stat/request.json', {
'rtype': 'path',
'start_date': formatted_date,
'end_date': formatted_date,
'granularity': 'day',
'area': 'china',
'domains': 'test.com'
})
if api['code'] == 200:
data_result = api['data']['result']
return data_result[0]['data']
else:
print("API failed: " + api['msg'])

修改密钥dogecloud_api方法中修改

access_key = 'xxxxx'
secret_key = 'xxxx'

修改域名 Get_trafficGet_reuestcount方法里面的 domains,把里面的内容改成现有在CDN部署的域名

api = dogecloud_api('/cdn/stat/request.json', {
'rtype': 'path',
'start_date': formatted_date,
'end_date': formatted_date,
'granularity': 'day',
'area': 'china',
'domains': 'test.com'
})

飞书发送卡片通知

这里需要修改创建机器人时的 webhook 和 签名

# 生成签名
def gen_sign(timestamp, secret):
string_to_sign = '{}\n{}'.format(timestamp, secret)
hmac_code = hmac.new(string_to_sign.encode("utf-8"), digestmod=hashlib.sha256).digest()
sign = base64.b64encode(hmac_code).decode('utf-8')
return sign


def send_message():
l7Flow_request_value, total_influx_megabytes, total_outflux_megabytes = get_Edgeone()
Dres = Get_traffic()
Dcount = Get_reuestcount()
current_time = datetime.now()
formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
timestamp = int(time.time())
sign = gen_sign(timestamp, "密钥")
data = {
"timestamp": timestamp,
"sign": sign,
"msg_type": "interactive",
"card": {
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "default",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "div",
"text": {
"content": "**🔴 报警服务:**\n腾讯云",
"tag": "lark_md"
}
}
]
},
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "div",
"text": {
"content": "**🕐 时间:**\n" + formatted_time + "",
"tag": "lark_md"
}
}
]
}
]
},
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "default",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "grey",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "markdown",
"content": "**今日请求数\n<font color='red'>" + str(
l7Flow_request_value) + "</font>**",
"text_align": "center"
}
]
}
]
}
]
},
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "grey",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "markdown",
"content": "**今日请求流量\n<font color='green'>" + str(
total_influx_megabytes) + " M</font>**",
"text_align": "center"
}
]
}
]
}
]
},
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "grey",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "markdown",
"content": "**今日响应流量\n<font color='blue'>" + str(
total_outflux_megabytes) + " M</font>**",
"text_align": "center"
}
]
}
]
}
]
}
]
},
{
"tag": "hr"
},
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "default",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "div",
"text": {
"content": "**🔴 报警服务:**\n多吉云",
"tag": "lark_md"
}
}
]
},
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "div",
"text": {
"content": "**🕐 时间:**\n" + formatted_time + "",
"tag": "lark_md"
}
}
]
}
]
},
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "default",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "grey",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "markdown",
"content": "**今日请求数\n<font color='red'>" + str(
Dcount[0]) + "</font>**",
"text_align": "center"
}
]
}
]
}
]
},
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "grey",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "markdown",
"content": "**今日请求流量\n<font color='green'>" + str(
Dres[0]) + " M</font>**",
"text_align": "center"
}
]
}
]
}
]
}
]
},
{
"tag": "hr"
},
{
"tag": "action",
"actions": [
{
"tag": "button",
"text": {
"content": "腾讯云 🌹",
"tag": "lark_md"
},
"type": "default",
"value": {},
"multi_url": {
"url": "https://cloud.tencent.com/"
"/overview",
"android_url": "",
"ios_url": "",
"pc_url": ""
}
},
{
"tag": "button",
"text": {
"content": "多吉云 🌹",
"tag": "lark_md"
},
"type": "default",
"value": {},
"multi_url": {
"url": "https://console.dogecloud.com/cdn/overview",
"android_url": "",
"ios_url": "",
"pc_url": ""
}
}
]
}
],
"header": {
"template": "red",
"title": {
"content": "CDN流量监控",
"tag": "plain_text"
}
}
}
}
headers = {
'Content-Type': 'application/json'
}
res = requests.post("webhook", json=data,
headers=headers)
print(res.json())

修改签名

sign = gen_sign(timestamp, "密钥")

修改webhook

res = requests.post("webhook", json=data,
headers=headers)

完整代码

代码每隔3个小时会执行一次 获取到信息 发送到飞书

import base64
import hashlib
import time
import schedule
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.teo.v20220901 import teo_client, models
from datetime import datetime
from hashlib import sha1
import hmac
import requests
import json
import urllib


def get_Edgeone():
try:
cred = credential.Credential("腾讯API密钥", "腾讯API密钥")
httpProfile = HttpProfile()
httpProfile.endpoint = "teo.tencentcloudapi.com"
clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
client = teo_client.TeoClient(cred, "", clientProfile)
current_datetime = datetime.utcnow()

start_of_day = current_datetime.replace(hour=0, minute=0, second=0, microsecond=0)

end_of_day = current_datetime.replace(hour=23, minute=59, second=59, microsecond=999999)

start_of_day_iso = start_of_day.strftime('%Y-%m-%dT%H:%M:%SZ')
end_of_day_iso = end_of_day.strftime('%Y-%m-%dT%H:%M:%SZ')
req = models.DescribeTimingL7AnalysisDataRequest()
params = {
"StartTime": start_of_day_iso,
"EndTime": end_of_day_iso,
"MetricNames": ["l7Flow_outFlux", "l7Flow_inFlux", "l7Flow_request"],
"ZoneIds": ["CDN ID"],
"Interval": "day",
"Area": "mainland"
}
req.from_json_string(json.dumps(params))

# 返回的resp是一个DescribeTimingL7AnalysisDataResponse的实例,与请求对象对应
resp = client.DescribeTimingL7AnalysisData(req)
# 输出json格式的字符串回包
print(resp.to_json_string())
data = json.loads(resp.to_json_string())
l7Flow_request_value = None

for item in data["Data"][0]["TypeValue"]:
if item["MetricName"] == "l7Flow_request":
l7Flow_request_value = item["Sum"]
break
total_influx = 0
total_outflux = 0

for item in data["Data"][0]["TypeValue"]:
if item["MetricName"] == "l7Flow_inFlux":
total_influx += item["Sum"]
elif item["MetricName"] == "l7Flow_outFlux":
total_outflux += item["Sum"]

total_influx_megabytes = round(total_influx / (1024 * 1024), 2)
total_outflux_megabytes = round(total_outflux / (1024 * 1024), 2)

print("访问请求:", l7Flow_request_value)
print("请求流量:", total_influx_megabytes)
print("响应流量:", total_outflux_megabytes)

return l7Flow_request_value, total_influx_megabytes, total_outflux_megabytes
except TencentCloudSDKException as err:
print(err)


# 多吉云API
def dogecloud_api(api_path, data={}, json_mode=False):
access_key = '多吉云密钥'
secret_key = '多吉云密钥'

body = ''
mime = ''
if json_mode:
body = json.dumps(data)
mime = 'application/json'
else:
body = urllib.parse.urlencode(data) # Python 2 可以直接用 urllib.urlencode
mime = 'application/x-www-form-urlencoded'
sign_str = api_path + "\n" + body
signed_data = hmac.new(secret_key.encode('utf-8'), sign_str.encode('utf-8'), sha1)
sign = signed_data.digest().hex()
authorization = 'TOKEN ' + access_key + ':' + sign
response = requests.post('https://api.dogecloud.com' + api_path, data=body, headers={
'Authorization': authorization,
'Content-Type': mime
})
return response.json()


# 获取流量数据
def Get_traffic():
current_time = datetime.now()
formatted_date = current_time.strftime("%Y-%m-%d")
api = dogecloud_api('/cdn/stat/traffic.json', {
'rtype': 'path',
'start_date': formatted_date,
'end_date': formatted_date,
'granularity': 'day',
'area': 'china',
'domains': 'CDN部署的域名'
})
if api['code'] == 200:
data_result = api['data']['result']

if data_result:
data_values = data_result[0]['data']
data_values_megabytes = [value / (1024 * 1024) for value in data_values]
print("Data values in Megabytes:", data_values_megabytes)
traffres = [round(value, 2) for value in data_values_megabytes]
return traffres
else:
print("No data available.")
else:
print("API failed: " + api['msg'])


# 获取请求数
def Get_reuestcount():
current_time = datetime.now()
formatted_date = current_time.strftime("%Y-%m-%d")
api = dogecloud_api('/cdn/stat/request.json', {
'rtype': 'path',
'start_date': formatted_date,
'end_date': formatted_date,
'granularity': 'day',
'area': 'china',
'domains': 'CDN部署的域名'
})
if api['code'] == 200:
data_result = api['data']['result']
return data_result[0]['data']
else:
print("API failed: " + api['msg'])


# 生成签名
def gen_sign(timestamp, secret):
string_to_sign = '{}\n{}'.format(timestamp, secret)
hmac_code = hmac.new(string_to_sign.encode("utf-8"), digestmod=hashlib.sha256).digest()
sign = base64.b64encode(hmac_code).decode('utf-8')
return sign


def send_message():
l7Flow_request_value, total_influx_megabytes, total_outflux_megabytes = get_Edgeone()
Dres = Get_traffic()
Dcount = Get_reuestcount()
current_time = datetime.now()
formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
timestamp = int(time.time())
sign = gen_sign(timestamp, "飞书机器人签名")
data = {
"timestamp": timestamp,
"sign": sign,
"msg_type": "interactive",
"card": {
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "default",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "div",
"text": {
"content": "**🔴 报警服务:**\n腾讯云",
"tag": "lark_md"
}
}
]
},
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "div",
"text": {
"content": "**🕐 时间:**\n" + formatted_time + "",
"tag": "lark_md"
}
}
]
}
]
},
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "default",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "grey",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "markdown",
"content": "**今日请求数\n<font color='red'>" + str(
l7Flow_request_value) + "</font>**",
"text_align": "center"
}
]
}
]
}
]
},
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "grey",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "markdown",
"content": "**今日请求流量\n<font color='green'>" + str(
total_influx_megabytes) + " M</font>**",
"text_align": "center"
}
]
}
]
}
]
},
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "grey",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "markdown",
"content": "**今日响应流量\n<font color='blue'>" + str(
total_outflux_megabytes) + " M</font>**",
"text_align": "center"
}
]
}
]
}
]
}
]
},
{
"tag": "hr"
},
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "default",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "div",
"text": {
"content": "**🔴 报警服务:**\n多吉云",
"tag": "lark_md"
}
}
]
},
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "div",
"text": {
"content": "**🕐 时间:**\n" + formatted_time + "",
"tag": "lark_md"
}
}
]
}
]
},
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "default",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "grey",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "markdown",
"content": "**今日请求数\n<font color='red'>" + str(
Dcount[0]) + "</font>**",
"text_align": "center"
}
]
}
]
}
]
},
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "column_set",
"flex_mode": "none",
"background_style": "grey",
"columns": [
{
"tag": "column",
"width": "weighted",
"weight": 1,
"vertical_align": "top",
"elements": [
{
"tag": "markdown",
"content": "**今日请求流量\n<font color='green'>" + str(
Dres[0]) + " M</font>**",
"text_align": "center"
}
]
}
]
}
]
}
]
},
{
"tag": "hr"
},
{
"tag": "action",
"actions": [
{
"tag": "button",
"text": {
"content": "腾讯云 🌹",
"tag": "lark_md"
},
"type": "default",
"value": {},
"multi_url": {
"url": "https://cloud.tencent.com/"
"/overview",
"android_url": "",
"ios_url": "",
"pc_url": ""
}
},
{
"tag": "button",
"text": {
"content": "多吉云 🌹",
"tag": "lark_md"
},
"type": "default",
"value": {},
"multi_url": {
"url": "https://console.dogecloud.com/cdn/overview",
"android_url": "",
"ios_url": "",
"pc_url": ""
}
}
]
}
],
"header": {
"template": "red",
"title": {
"content": "CDN流量监控",
"tag": "plain_text"
}
}
}
}
headers = {
'Content-Type': 'application/json'
}
res = requests.post("飞书机器人webhook", json=data,
headers=headers)
print(res.json())


def job():
print("Job started at", datetime.now())
send_message()


schedule.every(3).hours.do(job)

if __name__ == '__main__':
while True:
schedule.run_pending()
time.sleep(1)