探测资源的可用性,这事听起来简单,不就是“检查一下还能不能用”嘛。但真等到你负责的系统在半夜出故障,告警群里一堆人@你,你才发现负载均衡那边早就把后端标红了,而你的第一版探测脚本连个日志都没留下——那时候就晚了。我做了几年运维和SRE,被这种“看似简单”的事坑过不止一次,所以这次把系列第七篇的篇幅,专门留给“探测资源的可用性”这个话题。
它到底能做什么?往小了说,是写个脚本定时去探测某个网址、端口、数据库实例通不通;往大了说,是整个监控体系的基石,是服务治理、容量评估、故障恢复最原始的数据来源。不管是运维、后端开发,还是做自动化测试的同学,这套东西早晚都要用上。今天这篇,我尽量把工具选型、脚本设计、参数取舍、常见坑都讲透,给大家一份可以直接拿来改的参考。
1. 先搞清楚:你说的“资源”到底是什么
很多人一上来就写代码,结果写出来的探测脚本连“探测对象”都没划分清楚。资源不是一句“服务器”就能概括的,不同类型的资源,探测手段完全不同。
1.1 资源探测的对象分类
我在实际项目里,会把资源先分成几类:
- HTTP/HTTPS 接口:这类最常见,探测一个 URL 的状态,比如首页、健康检查端点、登录接口。
- TCP 端口:比如 MySQL 的 3306、Redis 的 6379、Kafka 的 9092,只要端口能建立 TCP 连接,就认为服务还在监听。
- 数据库/中间件:不只是端口通不通,还需要执行一条查询或者命令,比如 MySQL 的
SELECT 1,Redis 的PING,验证服务真的能响应业务请求。 - DNS 解析:探测一个域名能不能被正常解析到预期 IP,很多故障其实发生在 DNS 层,而不是应用层。
- 共享存储/对象存储:比如 NFS 挂载点、S3 bucket 能不能读写。
- 消息队列:比如 RabbitMQ、Kafka 的 broker 是否在集群内正常同步。
为什么要分这么细?因为探测方式的复杂度是递增的。TCP 端口探测只能证明“有进程在监听”,但证明不了“服务还能处理请求”。比如 MySQL 的连接数满了,端口照样能连上,但新的查询就会卡死或直接被拒绝,这时候只用端口探测就是典型的“假活”。
1.2 可用性不只有“通不通”一个维度
我把可用性分成三层,写探测脚本的时候必须想清楚你到底在测哪一层:
第一层是连通性:网络能不能到达,端口是否监听,握手是否成功。这是最底层,也是大多数脚本默认做的。
第二层是功能性:服务进程活着,且能完成一轮完整的业务交互。比如 Redis 不只是端口能连,还能 PING 返回 PONG;接口不只是返回 200,还得是预期的业务结果。
第三层是性能达标:服务虽然能响应,但响应时间是否在可接受范围内。比如一个接口平时 50ms,现在变成 5 秒,对用户来说这就是不可用。所以探测脚本里最好带上响应时间阈值,超过阈值就标记为 degraded,而不是简单地 up/down。
那么问题来了:一个端口通、但接口响应 3 秒的服务,算不算可用?我的建议是,监控层面单独分状态:UP、DOWN、DEGRADED。不要一拍脑袋搞成二值判断,否则后面告警规则很难写。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 工具选型:命令行工具能干到哪一步
在写完整探测程序之前,先用命令行工具做一轮快速验证,通常能省很多事。但命令行工具有它的适用范围,别拿锤子去拧螺丝。
2.1 ping、nc、telnet、curl 的适用边界
先说结论,我用一个表格总结一下各自的特点:
| 工具 | 探测能力 | 局限 |
|---|---|---|
| ping (ICMP) | 主机是否在线、网络延迟 | 很多云环境禁 ICMP,不一定可靠;只能测主机,不能测端口 |
| nc / telnet | TCP 端口是否可连接 | 不处理应用层协议,无法验证服务健康 |
| curl | HTTP/HTTPS 接口状态、响应时间、内容 | 需要额外处理超时、重试、代理环境变量 |
| dig / nslookup | DNS 解析是否正常 | 只能看到解析结果,无法直接判断应用状态 |
| openssl s_client | TLS 握手是否正常 | 主要用于证书过期检查,交互式使用比较繁琐 |
这里面坑最多的就是 ping。我在阿里云、腾讯云上都遇到过,明明服务正常,但 ping 丢包 100%,因为安全组或者云平台把 ICMP 协议直接挡掉了。这种情况你拿 ping 的结果当成探测依据,等于天天在误报。所以我的建议是:探测生产环境资源,尽量避开 ICMP,优先用 TCP 和 HTTP 层探测。
再看 curl。curl 功能很强大,但默认没有超时限制,如果一个接口卡住了,curl 会一直等下去,这在监控脚本里是大忌。用 curl 探测时至少加 --connect-timeout 和 --max-time,前者限制建立连接的时间,后者限制整个请求的时间。例如:
bash复制curl -sS -o /dev/null -w "%{http_code} %{time_total}" \
--connect-timeout 3 --max-time 5 \
https://api.example.com/health
这条命令会把 HTTP 状态码和总耗时打印出来,是个很实用的快速验证方式。
2.2 为什么最后还是要自己写程序
命令行工具适合“临时探一下”,但要落地成持续运行的监控任务,问题就来了:
- 多目标探测时,shell 串行执行效率太低;
- 每次结果没有结构化存储,无法自动关联时间、状态、历史;
- 重试逻辑、告警去重、状态切换这些逻辑,shell 写起来很别扭。
所以我的做法是:命令行工具用于调试和验证,正式监控任务用 Python 这类脚本语言写成一个独立的探测模块,这样后续加新资源类型、接告警平台都方便。下面的核心实现部分,我会给一个完整的脚本框架。
2.3 多维度组合探测:别只看单点
真正有用的资源探测,往往是组合式的。我曾经维护过一个老系统,健康检查接口本身很简单,只是返回一段固定字符串。某次故障里,后端服务的线程池已经打满了,但健康检查接口因为走的是另一个轻量线程池,依然返回 200。等我们接到用户投诉再去查,已经晚了。
从那之后,我给自己定了一条规则:业务关键资源至少要做两层探测。比如一个订单服务,第一层 TCP 端口探测确认进程
