最小可运行示例:用一条 curl 完成网站测速诊断全链路检查
出发点:先让一条请求跑通
做性能诊断类工具时,最容易陷入的第一步不是选型,而是连一次真实请求都发不出去。网站测速诊断接口的设计思路恰好符合“越简单越好”的原则:一个 GET 请求、一个必填参数、一组结构清晰的返回字段。本文围绕最小可运行示例展开,逐步把一条 curl 命令拆解为可复用的工程实践。
适用场景:什么时候需要这个接口
网站测速诊断接口适合以下场景:
- 发布前巡检:上线前确认目标站点从公网访问时 DNS 解析、TCP 连接、SSL 握手均正常,且 TTFB 在合理范围内。
- CDN 切换验证:切换 CDN 或回源策略后,用接口观察最终命中的 URL、重定向次数和耗时分布,快速判断链路是否生效。
- 定时监控脚本:利用 QPS 2/s 的额度,对少量核心 URL 做低频轮询,把总耗时和 HTTP 状态码写入日志。
- 故障复盘:用户反馈“打开慢”时,通过一次请求拿到 DNS、TCP、SSL、TTFB、总耗时五项数据,定位瓶颈出在哪一层。
需要说明的是,该接口返回的是测量时刻的一次性快照,不适合作为长期性能基线的唯一数据源——单次结果受网络波动影响较大,建议多次采样后取中位数。
接口能力边界
接口位于https://v1.apizero.cn/api/site-check,方法为 GET,一次请求返回六类信息:
- DNS 解析耗时
- TCP 连接耗时
- SSL 握手耗时
- TTFB(首字节时间)
- 总耗时
- 重定向链、SSL 证书摘要、命中 IP/端口、页面体积等辅助信息
限速为 2 QPS,即每秒最多两次请求。若用于批量巡检,需要在调用侧自行控制频率。
参数与鉴权
Query 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url | string | 是 | 目标 URL,自动补https://前缀 |
传参时只需要给裸域名或路径即可,接口会自动补充协议头。例如url=baidu.com和url=https://baidu.com效果相同。
Header 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
Authorization | string | 是 | API Key,按文档要求配置 |
实际发送请求时,示例中使用的是X-API-Key请求头。具体以接口文档的鉴权说明为准。
最小可运行示例:一条 curl 命令
先写一个最精简的形式,只需要替换 URL 占位符和目标地址:
curl -sS \ -X GET \ -H "X-API-Key: $APIZERO_API_KEY" \ "https://v1.apizero.cn/api/site-check?url=<url>"把环境变量APIZERO_API_KEY替换为真实 Key,将<url>替换为待测站点:
curl -sS \ -X GET \ -H "X-API-Key: your-api-key-here" \ "https://v1.apizero.cn/api/site-check?url=example.com"若当前 shell 已配置APIZERO_API_KEY环境变量,直接复用第一条即可。
加一点可读性
用jq格式化输出,方便直接观察字段层级:
curl -sS \ -X GET \ -H "X-API-Key: $APIZERO_API_KEY" \ "https://v1.apizero.cn/api/site-check?url=example.com" | jq .输出的 JSON 结构如下:
{ "code": 0, "data": { "final_url": "https://www.example.com/", "http_code": 200, "redirect_count": 1, "timing": { "connect_ms": 32.5, "dns_ms": 15, "ssl_ms": 78.4, "total_ms": 156.7, "ttfb_ms": 145.2 }, "url": "https://example.com" }, "msg": "成功" }返回值逐段拆解
顶层字段
| 字段 | 类型 | 含义 |
|---|---|---|
code | number | 业务状态码,0表示成功 |
msg | string | 状态描述 |
data | object | 核心数据体 |
data 对象
| 字段 | 类型 | 含义 |
|---|---|---|
url | string | 请求时传入的原始 URL |
final_url | string | 经过重定向后的最终 URL |
http_code | number | 最终响应的 HTTP 状态码 |
redirect_count | number | 重定向次数 |
timing | object | 耗时明细,单位毫秒 |
timing 对象
| 字段 | 类型 | 含义 |
|---|---|---|
dns_ms | number | DNS 解析耗时 |
connect_ms | number | TCP 连接建立耗时 |
ssl_ms | number | SSL/TLS 握手耗时 |
ttfb_ms | number | 从发起请求到收到响应首字节的耗时 |
total_ms | number | 总耗时 |
一个常见误区是认为total_ms等于五个分项之和。实际上ttfb_ms已经包含了 DNS、TCP、SSL 的时间,total_ms则进一步包含内容下载时间,因此不要对它们直接做加法。正确的关系是:ttfb_ms覆盖响应首字节之前的所有阶段,total_ms覆盖完整请求周期。
常见错误与排查思路
401 鉴权失败
现象:返回 HTTP 401 或业务码提示 Key 无效。
排查步骤:
- 确认
X-API-Key头名称与文档一致。 - 确认 Key 前后没有误加空格或换行。
- 确认环境变量
APIZERO_API_KEY已正确导出:echo $APIZERO_API_KEY。
参数缺失或格式错误
现象:url参数为空、缺失或包含非法字符。
排查步骤:
- 检查 URL 是否做了 shell 转义,特别是包含
&、?时需要用引号包裹整个地址。 - 检查自动补全逻辑——如果传入了不完整的域名,接口会尝试补
https://,但明显非法的字符串仍可能被拒绝。
目标站点不可达
现象:http_code为 0 或final_url为空。
这种情况下重点看data里是否有错误描述字段,或观察timing中卡在哪个阶段——例如dns_ms异常高则疑似 DNS 解析问题,connect_ms超时则可能与目标端口或防火墙相关。
工程化注意事项
1. 频率控制
接口 QPS 为 2/s,批量检测时务必在代码中加节流。简单做法是每次请求后 sleep 500ms 以上,或用令牌桶限制并发。
2. URL 编码
当目标 URL 包含路径、查询参数时,需要先做 URL 编码再拼接到请求中。以下 Python 示例演示了正确处理方式:
import time import urllib.parse import urllib.request import json API_URL = "https://v1.apizero.cn/api/site-check" API_KEY = "your-api-key-here" TARGET = "https://example.com/path?ref=test&lang=zh" encoded = urllib.parse.quote(TARGET, safe="") request = urllib.request.Request( f"{API_URL}?url={encoded}", headers={"X-API-Key": API_KEY}, method="GET", ) with urllib.request.urlopen(request) as resp: result = json.loads(resp.read().decode("utf-8")) print(result["data"]["timing"]) time.sleep(0.6) # 控制在 QPS 范围内注意:safe=""确保包括冒号和斜杠在内的特殊字符全部被编码,避免?和&影响服务端参数解析。
3. 重定向与 final_url 的利用
redirect_count大于 0 时,业务方应确认final_url是否与预期一致。例如配置了回源策略的站点,检测结果中若出现额外跳转,可能意味着配置有误。
4. 超时处理
网络诊断类接口的耗时取决于目标站点状态,极端情况下可能较慢。客户端请求超时建议设置在 30 秒以上,避免误判为接口故障。
5. 结果落库策略
建议按“站点 + 时间点 + 耗时明细”三要素存储。查询时按站点分组、按时间倒序,方便观察趋势。不要只存总耗时——TTFB 与 SSL 耗时分开记录,才能真正定位性能劣化层级。
从最小示例到工具脚本
把 curl 替换成脚本后,整个流程可以收敛为三步:
- 准备目标 URL 列表。
- 循环调用接口,每次请求间隔 600ms 以上。
- 将
code=0的返回内容写入 JSON Lines 文件,code!=0的记录到错误日志。
以下是一个贴近生产的最小脚本骨架:
# site_check_snapshot.py import json import time import urllib.parse import urllib.request API = "https://v1.apizero.cn/api/site-check" KEY = "your-api-key-here" TARGETS = ["example.com", "example.org"] def check(url: str) -> dict: encoded = urllib.parse.quote(url, safe="") req = urllib.request.Request( f"{API}?url={encoded}", headers={"X-API-Key": KEY}, method="GET", ) with urllib.request.urlopen(req, timeout=30) as resp: return json.loads(resp.read().decode("utf-8")) for target in TARGETS: try: payload = check(target) if payload.get("code") == 0: with open("snapshot.jsonl", "a", encoding="utf-8") as f: f.write(json.dumps(payload, ensure_ascii=False) + "\n") else: print(f"{target} 业务异常: {payload}") except Exception as exc: print(f"{target} 请求失败: {exc}") time.sleep(0.6)这个脚本不依赖第三方库,Python 3.8+ 可直接运行。需要调整的只有KEY与TARGETS两处。
参考文档
- 网站测速诊断文档页:https://apizero.cn/aidocs/site-check
- 原始 Markdown 文档:https://apizero.cn/aidocs/site-check/raw.md