最稳妥方案是用 requests.get() 检查状态码,设 timeout、allow_redirects=true,捕获 requestexception;200/204/301/302/307 视为存活,5xx 需告警,注意 headers 防 waf 拦截,并添加重试、日志和异常分类。

用 requests.get() 检查状态码是最直接的方式
Python 中最常用、最稳妥的方案就是 requests 库发 GET 请求,然后看 response.status_code 是否落在 2xx 或 3xx 范围。别用 urllib 手动处理重定向和超时——它默认不跟随重定向,容易把 301/302 误判为“不可用”。
关键点:
- 必须设
timeout(建议 5–10 秒),否则 DNS 卡住或服务无响应会阻塞整个脚本 - 加
allow_redirects=True(requests默认就是 True,但显式写上更安心) - 避免只检查
status_code == 200,有些健康接口返回 204 或 302 也算正常 - 别忽略
requests.exceptions.RequestException类异常,网络断、DNS 失败、SSL 验证失败都会抛这个基类
哪些状态码该算“存活”,哪些必须告警
不能一概而论“非 200 就挂了”。真实场景中:
-
200、204、301、302、307通常表示服务可路由、能响应——只要不是你明确不接受的跳转(比如跳到维护页),就可视为存活 -
400、401、403说明服务活着,只是请求不合法或没权限——这类不该触发“宕机”告警,但可单独记录用于审计 -
404要分情况:监控的是根路径/却返回 404,大概率配置出错;监控的是/health接口却 404,说明健康检查端点没部署 -
5xx(尤其是500、502、503、504)一律视为服务异常,需告警
避免被 CDN 或 WAF 拦截导致误判
很多站点在 Cloudflare、阿里云 WAF 后面,会拦截无 User-Agent 或行为异常的请求,返回 403 或直接断连。这不是服务挂了,是你的探测请求被当成了爬虫。
解决办法很简单:
- 加一个合理
headers,比如{"User-Agent": "UptimeMonitor/1.0"} - 如果目标有登录态要求(如内网后台),得带上有效
cookies或Authorizationheader - 别高频轮询(比如 1 秒一次),WAF 可能按 IP 限速;生产环境建议 ≥30 秒间隔
- 若仍被拦,可尝试用
requests.Session()复用连接,减少指纹特征
超时、重试、日志——脚本上线前必须补上的三件事
裸跑一个 requests.get() 在生产环境等于没写。真正可用的监测脚本必须包含:
- 两次重试(
requests.adapters.HTTPAdapter(max_retries=2)),避免偶发网络抖动误报 - 结构化日志:至少记录 URL、状态码、耗时(
response.elapsed.total_seconds())、错误类型(str(e)) - 区分“不可达”(
ConnectionError)、“超时”(Timeout)、“协议错误”(InvalidURL)等底层异常,方便定位是网络问题还是配置错误 - 别把所有异常都吞掉并 print("failed")——这样你永远不知道是证书过期、域名解析失败,还是对方关了 HTTP 端口
复杂点在于,HTTP 状态码只是表层信号;真正的可用性还得结合响应体内容(比如 /health 返回 JSON 中的 "status": "ok")、TLS 证书有效期、DNS 解析结果。这些要加就得引入额外逻辑,容易让脚本变重——先稳住状态码这一层,再逐步叠加。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











