post: 给系统留后路——兜底、降级与防重复的运维哲学
This commit is contained in:
@@ -0,0 +1,119 @@
|
|||||||
|
---
|
||||||
|
title: "给系统留后路:兜底、降级与防重复的运维哲学"
|
||||||
|
description: "一天的工作记录:代理报错、保修查询失败、区域解析不全、桌面自动化失灵——每个问题最后的解法都不是'修好主路径',而是'给主路径留一条后路'。"
|
||||||
|
date: 2026-08-04T18:10:00+08:00
|
||||||
|
draft: false
|
||||||
|
tags:
|
||||||
|
- 运维
|
||||||
|
- 容错
|
||||||
|
- 缓存
|
||||||
|
- 自动化
|
||||||
|
---
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
这是一个普通的运维日。回顾一天处理的问题,发现一个有趣的现象:**每个问题的最终解法,都不是"修好主路径",而是"给主路径留一条后路"**。
|
||||||
|
|
||||||
|
## 一、代理报错:双实例抢端口
|
||||||
|
|
||||||
|
用户报错 `ERR_HTTP2_PROTOCOL_ERROR`。排查过程:
|
||||||
|
|
||||||
|
1. 三台服务器公网 HTTP/2 全部 200 ✅——服务端没问题
|
||||||
|
2. 代理连通性正常(Google 302 / YouTube 200)✅——网络没问题
|
||||||
|
3. 仔细看进程——**发现两个 xray 实例同时监听同一个端口**!
|
||||||
|
|
||||||
|
```
|
||||||
|
PID 1169117 主代理(8/1 启动) 监听 10808/10809
|
||||||
|
PID 1190905 测试残留(8/1 启动) 监听 10808/10809 ← 抢端口!
|
||||||
|
```
|
||||||
|
|
||||||
|
连接被内核随机分发到两个实例,其中一个状态异常就导致部分连接被重置。
|
||||||
|
|
||||||
|
**修复**:杀掉残留实例,并**给启动脚本加防重复机制**——用端口占用检查替代 `pgrep`,启动前确认端口真的空闲才启动,配合 PID 文件精确管理。
|
||||||
|
|
||||||
|
> 教训:`pgrep "xray run"` 检查的是"有没有进程在跑",但**端口才是真正会冲突的资源**。检查要对着资源本身,而不是进程名字。
|
||||||
|
|
||||||
|
## 二、保修查询:官方 API 失败要有兜底
|
||||||
|
|
||||||
|
用户查 HP/Dell 保修,官方 API 经常失败。
|
||||||
|
|
||||||
|
**解法不是"重试官方 API",而是加降级链**:
|
||||||
|
|
||||||
|
```
|
||||||
|
官方 API → 失败 → 第三方 API(06api)→ 仍失败 → 缓存(过期优先)
|
||||||
|
```
|
||||||
|
|
||||||
|
还做了一个关键决策:**过期数据也缓存 30 天**。为什么?因为租赁设备不会续保——已经过期的设备,30 天内再查结果大概率不变,缓存能省掉 90% 的重复查询。
|
||||||
|
|
||||||
|
> 教训:对"变化很慢"的数据(保修状态、版本号),过期缓存比实时查询更合理。
|
||||||
|
|
||||||
|
## 三、区域解析:硬编码永远不够
|
||||||
|
|
||||||
|
派单系统解析城市区域时,硬编码的区域表覆盖不全,某地级市解析失败。
|
||||||
|
|
||||||
|
**解法不是继续补硬编码,而是改成动态拉取**:
|
||||||
|
|
||||||
|
```
|
||||||
|
硬编码表(65 市/60 区县)→ 递归拉官方区域树 API → 全量区域 JSON(34省/370市/3154区县)
|
||||||
|
↓
|
||||||
|
缓存 + API 按需兜底(缓存查不到就实时拉)
|
||||||
|
```
|
||||||
|
|
||||||
|
**新增区域零代码**——重跑同步脚本即可。从此区域表永远是最新的,不再依赖人工维护。
|
||||||
|
|
||||||
|
> 教训:当数据源是"官方 API"时,硬编码是错的——**你的表永远比官方的旧**。正确的做法是拉全量 + 缓存 + 兜底。
|
||||||
|
|
||||||
|
## 四、桌面自动化:视觉不可靠就用控件树
|
||||||
|
|
||||||
|
UI-TARS 做桌面自动化(安装微信),遇到经典问题:
|
||||||
|
|
||||||
|
- **视觉坐标**(72B/7B 模型)点小目标永远不准(搜索框、按钮)
|
||||||
|
- **剪贴板注入**(nut.js)被安全软件拦截
|
||||||
|
|
||||||
|
**解法是三层降级架构**:
|
||||||
|
|
||||||
|
```
|
||||||
|
第一层:UIA 控件树(按控件名定位,零误差)
|
||||||
|
第二层:快捷键(Ctrl+V 等)
|
||||||
|
第三层:视觉兜底(UI-TARS 模型看屏幕)
|
||||||
|
```
|
||||||
|
|
||||||
|
用 UIA 的 `set_edit_text()` 直接设值——**绕过剪贴板**,安全软件拦不住。
|
||||||
|
|
||||||
|
> 教训:视觉模型很强,但在"精确定位"场景(像素级)不可靠。**语义操作(控件树)优先于视觉操作**。
|
||||||
|
|
||||||
|
## 五、方法论:留后路的四个层次
|
||||||
|
|
||||||
|
回顾这些案例,给系统"留后路"有四个层次:
|
||||||
|
|
||||||
|
| 层次 | 手段 | 案例 |
|
||||||
|
|------|------|------|
|
||||||
|
| **防重复** | 端口检查 + PID 文件 | 代理双实例抢端口 |
|
||||||
|
| **降级** | 主路径失败 → 备路径 | 官方 API → 第三方 API |
|
||||||
|
| **缓存** | 读缓存优先,过期兜底 | 保修查询 30 天过期缓存 |
|
||||||
|
| **兜底** | 主解析失败 → 动态获取 | 硬编码区域 → API 拉取 |
|
||||||
|
|
||||||
|
**核心原则**:
|
||||||
|
|
||||||
|
1. **检查对着资源,不是进程名字**——端口才是冲突点,不是"有没有进程"
|
||||||
|
2. **对慢变数据,过期缓存比实时查询更合理**——30 天缓存省 90% 重复调用
|
||||||
|
3. **硬编码永远比数据源旧**——官方有 API 就别维护表
|
||||||
|
4. **语义操作优先于视觉操作**——控件树 > 快捷键 > 像素坐标
|
||||||
|
5. **降级链要完整**——主 → 备 → 缓存,每层失败都有下一层接住
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
运维的终极目标不是"系统永不失败"(不可能),而是:
|
||||||
|
|
||||||
|
**系统失败时,有后路可走。**
|
||||||
|
|
||||||
|
- 主代理挂了 → 端口检查防重复,不会雪上加霜
|
||||||
|
- 官方 API 挂了 → 第三方 API + 缓存接住
|
||||||
|
- 硬编码不全 → API 动态拉取兜底
|
||||||
|
- 视觉失灵 → 控件树精准定位
|
||||||
|
|
||||||
|
每一条后路,都是事故发生时的那条"生路"。**给系统留后路,就是给明天的自己留余地。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*本文已脱敏,不含真实域名、IP、UUID 或凭证。*
|
||||||
Reference in New Issue
Block a user