对于运维监控来说,系统运行时 API 监控是一个容易忽视的监控类别。一般情况下系统运行时 API 监控会有两种责任人情况:1. 质量管理部门负责;2. 运维部门负责。同时还会遇到开发测试和线上测试使用不同的监控策略、API 地址等环境差异。针对这个情况,需要有一个方案来打通开发时测试,到运行时测试,再到 API 告警的全流程。
架构图
开发测试、预发布测试、生产测试环境三者互相独立,使用数据同步的方式,将 API 接口测试集合同步到各个环境,这样子质量管理部门只需要在开发测试环节调试好自动化 API 参数,等待业务正式上线时就可以直接应用上对应的 API 测试集合,极大提升测试工作效率。
同时,对于接口告警,也会根据在生产环境由 API 接口测试集合的结果,自动过滤异常的接口进行告警。
[[Excalidraw/YAPI 落地全流程.excalidraw]]
部署
YApi 目前已经有一段时间没有更新了,但是功能依旧正常,后面有大佬在 YApi 的基础上出了 YApi Pro 项目地址,后续可以参考 YApi Pro 的相关文档进行操作。
部署部分可以参考 YApi Pro 官方部署文档
我们内部对 YApi 进行了容器化打包,也做了一些修改,因为容器挂载出来的数据目录不变,所以容器化后 YAPI 版本分发、升级时更高效。
使用
注册登录啥的我这边就直接跳过了,基础使用也不讲了,主要展开讲如何进行自动化接口测试并进行告警。
配置自动化检测
自动化测试告警流程图
配置 API 检测
自动化接口测试需要用到「服务端测试」功能
原理是,在外部通过定时任务调用 YApi 的测试接口,进行接口自动化测试
线上环境不需要时时刻刻进行 API 测试,故配置 Crontab 结合 shell 脚本,定期调用 YAPI 进行接口测试;同时可以通过测试集合的拆分,依照 API 重要程度,可划分出高频 API、低频 API,差异化进行 API 测试。
[root@ga-k8s01:/opt/devops] # cat /app/yapi/demo/runtest.sh
#!/bin/bash
source /etc/profile
con_name=`docker ps |grep yapi |awk '{print $1}'`
echo $con_name
time=$(date "+%Y%m%d%H%M%S")"_report.html"
echo $time
echo '==================================='
cd /app/yapi/test_report/demo
con_name_result=`/usr/bin/docker exec $con_name curl -X GET 'http://172.20.0.21:8084/api/open/run_auto_test?id=125&token=afe46de45617505c3bac&env_http_28=fs&mode=html&email=true'`
con_name_url=`echo $con_name_result | awk -F',' '{print $NF}' | awk -F'"' '{print $4}'`
echo $con_name_result > /app/yapi/test_report/demo/$time
使用上述脚本便可以调用 yapi 进行自动化测试。脚本中的 curl
地址就是对应上放截图的测试集合「服务端自动化测试」的请求地址。
配置异常 API 过滤
使用下方脚本过滤 yapi 测试报告内的异常接口。
[root@ga-k8s01:/opt/devops] # cat gtest-api-error.sh
#!/bin/bash
# 检查是否提供了报告文件夹路径
if [ -z "$1" ]; then
echo "请提供报告文件夹路径作为参数。"
exit 1
fi
# 默认报告文件夹路径
report_dir="/app/yapi/test_report/demo"
# 获取报告文件夹路径
report_dir="$1"
# 获取最新的报告文件
latest_report=$(ls -1t "${report_dir}"/*.html 2>/dev/null | head -n 1)
if [ -n "${latest_report}" ]; then
report_content=$(grep -oP '<div class="summary"><div>.*?</div></div>' "${latest_report}" | sed -e 's/<[^>]*>//g')
#echo "${report_content}"
if [ -n "${report_content}" ]; then
echo "自动化测试报告 ${latest_report} 概述:"
echo "------------------------------------"
echo "${report_content}"
echo "------------------------------------"
else
echo "未找到符合条件的文件。"
fi
# 使用 grep 和 sed 过滤验证失败的接口名字
failed_interfaces=$(grep -o '<a class="list" href="#[0-9]\+">[^<]\+</a> <div title="验证失败"' "${latest_report}" | sed -e 's/.*<a class="list" href="#[0-9]\+">//g' -e 's/<\/a>.*//g')
if [ -n "${failed_interfaces}" ]; then
echo "验证失败的接口名字"
echo "${failed_interfaces}"
echo "------------------------------------"
else
echo "接口均测试通过"
echo "------------------------------------"
fi
else
echo "未找到报告文件"
fi
配置 API 告警
使用脚本,在 API 检测完毕后自动调用告警脚本,将异常的 API 接口通过告警平台发出。
[root@ga-k8s01:/opt/devops] # cat apitestpush_demo.sh
#!/bin/bash
# 检查是否提供了应用名称
if [ -z "$1" ]; then
echo "请提供报告文件夹路径作为参数。"
exit 1
fi
# 检查是否提供了报告文件夹路径
if [ -z "$2" ]; then
echo "请提供报告文件夹路径作为参数。"
exit 1
fi
# 获取当前时间
time_now=$(date "+%Y-%m-%d %H:%M:%S")
# 应用名称 (假设需要提供应用名称)
app_name="$1"
# 运行提取报告的脚本并获取结果
test_result=$(/usr/bin/sh /opt/devops/gtest-api-error.sh "$2")
# 发送报告结果到指定 URL
if echo "${test_result}" | grep -q "全部验证通过"; then
echo "所有测试用例全部验证通过,不发送报警。"
else
echo "存在未通过的测试用例,发送报警。"
# 使用 jq 生成 JSON 数据
json_data=$(jq -n \
--arg app_name "$app_name" \
--arg time_now "$time_now" \
--arg gtest_result "$test_result" \
'{
content: ("级别状态:P2 报警\n策略名称:接口测试异常\n报警策略:" + $app_name + "\n设备名称:ga-k8s01\n触发时间:" + $time_now + "\n报警详情:\n" + $test_result)
}')
# 发送结果报告
curl -X POST www.alarm.com/api/XXXXXXXXX \
-H 'content-type: application/json' \
-d "$json_data"
fi
配置定时任务
[root@ga-k8s01:/opt/devops] # crontab -l
# YApi 自动化测试
0 10-23/2 * * * . /etc/profile; /bin/sh /app/yapi/demo/runtest.sh > /app/yapi/test_log/output.log 2>&1
# YApi 自动化测试告警推送
# 定时任务,脚本路径_不用变,应用名字_要改,gtest的报告路径_要改
10 9-23/2 * * * /usr/bin/bash /opt/devops/apitestpush_demo.sh FS /app/yapi/test_report/demo
# YApi 定时删除测试报告
0 0 * * 6 /bin/rm -rf /app/yapi/test_report/demo/*
告警样例
级别状态:P2 报警
策略名称:接口测试异常
报警策略:XXX
设备名称:ga-k8s01
触发时间:2024-06-05 21:10:01
报警详情:
自动化测试报告 /app/yapi/test_report/demo/20240605200001_report.html 概述:
------------------------------------
一共 204 测试用例, 203 个验证通过, 1 个未通过, 0 个跳过 616.62s
------------------------------------
验证失败的接口名字
getDemoCountV2
------------------------------------
@所有人
写在最后
- 对于整体程序 API 情况可以使用此方案
- 如果需要更高频率或者更高效的的 API 测试,建议还是手搓
curl
脚本进行监控 Crontab
通过一些特殊方案是可以做到秒级别的调用,但是对于 YApi 的场景不建议间隔时间太短