InstaBox 免费机挂起 no_capacity:信号抖动与真挂起的区分实战
InstaBox 免费机挂起 no_capacity:信号抖动与真挂起的区分实战
现象:一台机器突然显示已挂起
2026 年 11 月 5 日下午 14:44,一台一直在跑保活巡检的免费虚拟机突然上报状态为已挂起,平台侧给出的最后错误是 no_capacity。最近一次续租成功是 13:54:57,租约到期时间是 14:55:01。保活脚本的自愈续租返回了 409 machine_not_running,复查后机器仍然是挂起状态,告警邮件随即发出。
这台机器之前一直跑得很稳:50 分钟续一次租约,10 分钟巡检一次,7 小时一个 suspend-resume 周期。第一反应很容易走偏:以为是客户端掉了、网络断了,急着去重启客户端、重启机器。但这次的症状和以往的信号抖动完全不同,处理方法也完全不同。区分"信号抖动"和"真挂起",是保活巡检里最关键的一次判断。
先分清三种状态:抖动、列表过期、真挂起
免费机的状态显示有三层,混在一起查就会误判。
第一种是信号抖动。表现是服务端日志里 CONNECTED 和 DISCONNECTED 在一分钟内同步来回翻,几台机器同时出现同样的翻动。这是服务端信令侧的抖动,重启客户端修不好它,等一会儿自己就过去了。判断依据是翻动是同步的、短暂的,机器本身的租约和心跳并没有断。
第二种是 App 列表过期。表现是手机 App 里机器显示灰色离线,但服务端最后一次上报却是 CONNECTED/ready,心跳也还活着。这是 App 端的列表缓存没刷新,不是机器真掉了。正确动作是下拉刷新列表,或者重启 App 再点一下测试,而不是去重启机器。重启机器对这个症状是纯负收益,还可能打断一个好好的租约周期。
第三种就是这次的真挂起。机器自身上报 state=suspended,平台给出明确的最后错误 no_capacity,自愈续租返回 409 machine_not_running,复查后状态不变。租约到期时间 14:55:01 就在眼前,续租接口直接拒绝,因为机器根本不在运行状态。这不是显示问题,是平台侧因为容量不足把机器挂起了。
三者的处理路径完全不同:抖动等一等,列表过期刷新 App,真挂起走平台侧恢复。把真挂起当成抖动去等,会错过租约窗口;把抖动当成真挂起去重启,会白白折腾一台好机器。
判断:看三个证据,再决定动哪一层
我现在固定的判断顺序是这样的。先看机器自身上报的状态字段:state 是 suspended 还是 running。再看平台给出的最后错误:有没有 no_capacity 这类明确的容量错误。最后看自愈续租的返回码:409 machine_not_running 意味着续租接口已经明确拒绝,因为目标机器不在运行。
# 真挂起的三个证据(本次实测)
state=suspended # 机器自身上报已挂起
lastError=no_capacity # 平台最后错误:容量不足
renew.sh -> 409 machine_not_running # 自愈续租被明确拒绝
last successful renewal 13:54:57 # 租约续期停在 50 分钟前
lease expiry 14:55:01 # 租约到期时间已逼近
三个证据齐了,就不要再去重启客户端。客户端重启解决的是本地连接问题,平台侧容量不足不在它的管辖范围。正确动作是发告警、记录现场、等平台侧恢复容量,或者按平台规则重新申请资源。重启客户端这一步,在这个场景下可以省掉。
反过来,如果只有 App 显示灰色,但服务端最后上报是 CONNECTED/ready、心跳 alive,那就不要动机器,先刷新 App 列表。这是之前沉淀过的判断,至今仍然有效。
一个反例:7 小时周期曾经的假故障
同样是这套保活,之前还出过一次假故障。有一台机器的 7 小时 suspend-resume 周期一直跑不起来,日志里看不到完整的周期。查到最后,根因是周期脚本里写错了机器 ID,续租和挂起操作发到了错误的机器上。改掉那一行之后,第一次真实日志就证明了周期是通的:一个超过 7 小时的段、一次只断开 19 秒的挂起恢复、然后从 04:53:10Z 开始一个新段。
这个反例说明两件事。第一,保活脚本自身的配置错误,也会伪装成平台问题,排障时先核对脚本里的机器 ID、租约时间这些基本量,再怀疑平台。第二,一次成功的周期只能证明那一次跑通了,不能证明以后每次都通。周期性的东西,要看连续几轮的日志,不能拿一次成功当成永久结论。
巡检日志怎么写才有用
这次事件之后,我把巡检日志的写法也固定下来了。每次巡检记录五项:服务状态、最新一次续租时间、租约到期时间(换算成北京时间)、机器状态、最近两次成功续租时间。任一台不健康(服务非 active、最新续租超过 65 分钟未更新、机器非 running),就在段首加粗标异常。
65 分钟这个阈值是有来历的:续租周期是 50 分钟,超过 65 分钟没更新,说明至少错过了一次续租窗口,再等下去租约就要到期了。这次事件里,14:44 发现挂起时,最新续租停在 13:54:57,正好卡在阈值附近,巡检及时标了异常,告警邮件才发得出去。
另外,租约到期时间一定要换算成北京时间再记。平台给的是 UTC,14:55:01 UTC 和 14:55:01 北京时间差了 8 小时,记混了就会误判窗口。每次巡检把到期时间换算好写进日志,事后复盘才不会算错账。
踩过的坑
第一个坑是把信号抖动当成机器掉了。几台机器同时一分钟内连断翻动,看着吓人,其实是服务端信令抖动。重启客户端修不好,还会打断租约。正确动作是等,看同步性和持续时间。
第二个坑是 App 显示灰色就重启机器。服务端最后上报 CONNECTED/ready、心跳 alive 时,灰色只是 App 列表没刷新。下拉刷新或者重启 App 就够了,重启机器是白折腾。
第三个坑是真挂起时还在客户端层面找原因。no_capacity 加 409 machine_not_running,已经是平台侧的明确答复,继续重启客户端、重连网络都不会改变结果。这时候该做的是发告警、记现场、等平台侧恢复。
第四个坑是巡检脚本自己的配置错误伪装成平台故障。机器 ID 写错一行,周期跑不起来,看着像平台不给续租。排障先核对脚本里的基本量,再怀疑平台。
检查清单
机器状态异常时,按这个顺序走一遍:看机器自身上报的 state;看平台最后错误有没有 no_capacity;看自愈续租返回码是不是 409;看最新续租时间和租约到期时间(换算北京时间);App 灰色但服务端 CONNECTED/ready、心跳 alive 时先刷新 App 列表;同步短暂的连断翻动先等一等;三个真挂起证据齐了就发告警、记现场,不在客户端层面硬修。
把抖动、列表过期、真挂起三层分开,是免费机保活里最省时间的一个习惯。很多看起来是机器掉了的故障,查到最后只是显示层的问题;而真挂起时,最省时间的做法恰恰是停手、发告警、等平台。
- 点赞
- 收藏
- 关注作者
评论(0)