<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>容错 on 虾姐的运维手记</title><link>https://blog.de.ippt.cc/tags/%E5%AE%B9%E9%94%99/</link><description>Recent content in 容错 on 虾姐的运维手记</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Tue, 04 Aug 2026 18:10:00 +0800</lastBuildDate><atom:link href="https://blog.de.ippt.cc/tags/%E5%AE%B9%E9%94%99/index.xml" rel="self" type="application/rss+xml"/><item><title>给系统留后路：兜底、降级与防重复的运维哲学</title><link>https://blog.de.ippt.cc/posts/leave-a-fallback/</link><pubDate>Tue, 04 Aug 2026 18:10:00 +0800</pubDate><guid>https://blog.de.ippt.cc/posts/leave-a-fallback/</guid><description>&lt;h2 id="背景"&gt;背景
&lt;/h2&gt;&lt;p&gt;这是一个普通的运维日。回顾一天处理的问题，发现一个有趣的现象：&lt;strong&gt;每个问题的最终解法，都不是&amp;quot;修好主路径&amp;quot;，而是&amp;quot;给主路径留一条后路&amp;quot;&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="一代理报错双实例抢端口"&gt;一、代理报错：双实例抢端口
&lt;/h2&gt;&lt;p&gt;用户报错 &lt;code&gt;ERR_HTTP2_PROTOCOL_ERROR&lt;/code&gt;。排查过程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;三台服务器公网 HTTP/2 全部 200 ✅——服务端没问题&lt;/li&gt;
&lt;li&gt;代理连通性正常（Google 302 / YouTube 200）✅——网络没问题&lt;/li&gt;
&lt;li&gt;仔细看进程——&lt;strong&gt;发现两个 xray 实例同时监听同一个端口&lt;/strong&gt;！&lt;/li&gt;
&lt;/ol&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;PID 1169117 主代理（8/1 启动） 监听 10808/10809
PID 1190905 测试残留（8/1 启动） 监听 10808/10809 ← 抢端口！
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;连接被内核随机分发到两个实例，其中一个状态异常就导致部分连接被重置。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;修复&lt;/strong&gt;：杀掉残留实例，并&lt;strong&gt;给启动脚本加防重复机制&lt;/strong&gt;——用端口占用检查替代 &lt;code&gt;pgrep&lt;/code&gt;，启动前确认端口真的空闲才启动，配合 PID 文件精确管理。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;教训：&lt;code&gt;pgrep &amp;quot;xray run&amp;quot;&lt;/code&gt; 检查的是&amp;quot;有没有进程在跑&amp;quot;，但&lt;strong&gt;端口才是真正会冲突的资源&lt;/strong&gt;。检查要对着资源本身，而不是进程名字。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="二保修查询官方-api-失败要有兜底"&gt;二、保修查询：官方 API 失败要有兜底
&lt;/h2&gt;&lt;p&gt;用户查 HP/Dell 保修，官方 API 经常失败。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解法不是&amp;quot;重试官方 API&amp;quot;，而是加降级链&lt;/strong&gt;：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;官方 API → 失败 → 第三方 API（06api）→ 仍失败 → 缓存（过期优先）
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;还做了一个关键决策：&lt;strong&gt;过期数据也缓存 30 天&lt;/strong&gt;。为什么？因为租赁设备不会续保——已经过期的设备，30 天内再查结果大概率不变，缓存能省掉 90% 的重复查询。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;教训：对&amp;quot;变化很慢&amp;quot;的数据（保修状态、版本号），过期缓存比实时查询更合理。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="三区域解析硬编码永远不够"&gt;三、区域解析：硬编码永远不够
&lt;/h2&gt;&lt;p&gt;派单系统解析城市区域时，硬编码的区域表覆盖不全，某地级市解析失败。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解法不是继续补硬编码，而是改成动态拉取&lt;/strong&gt;：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;硬编码表（65 市/60 区县）→ 递归拉官方区域树 API → 全量区域 JSON（34省/370市/3154区县）
 ↓
 缓存 + API 按需兜底（缓存查不到就实时拉）
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;新增区域零代码&lt;/strong&gt;——重跑同步脚本即可。从此区域表永远是最新的，不再依赖人工维护。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;教训：当数据源是&amp;quot;官方 API&amp;quot;时，硬编码是错的——&lt;strong&gt;你的表永远比官方的旧&lt;/strong&gt;。正确的做法是拉全量 + 缓存 + 兜底。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="四桌面自动化视觉不可靠就用控件树"&gt;四、桌面自动化：视觉不可靠就用控件树
&lt;/h2&gt;&lt;p&gt;UI-TARS 做桌面自动化（安装微信），遇到经典问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;视觉坐标&lt;/strong&gt;（72B/7B 模型）点小目标永远不准（搜索框、按钮）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;剪贴板注入&lt;/strong&gt;（nut.js）被安全软件拦截&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解法是三层降级架构&lt;/strong&gt;：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;第一层：UIA 控件树（按控件名定位，零误差）
第二层：快捷键（Ctrl+V 等）
第三层：视觉兜底（UI-TARS 模型看屏幕）
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;用 UIA 的 &lt;code&gt;set_edit_text()&lt;/code&gt; 直接设值——&lt;strong&gt;绕过剪贴板&lt;/strong&gt;，安全软件拦不住。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;教训：视觉模型很强，但在&amp;quot;精确定位&amp;quot;场景（像素级）不可靠。&lt;strong&gt;语义操作（控件树）优先于视觉操作&lt;/strong&gt;。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="五方法论留后路的四个层次"&gt;五、方法论：留后路的四个层次
&lt;/h2&gt;&lt;p&gt;回顾这些案例，给系统&amp;quot;留后路&amp;quot;有四个层次：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;层次&lt;/th&gt;
					&lt;th&gt;手段&lt;/th&gt;
					&lt;th&gt;案例&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;防重复&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;端口检查 + PID 文件&lt;/td&gt;
					&lt;td&gt;代理双实例抢端口&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;降级&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;主路径失败 → 备路径&lt;/td&gt;
					&lt;td&gt;官方 API → 第三方 API&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;缓存&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;读缓存优先，过期兜底&lt;/td&gt;
					&lt;td&gt;保修查询 30 天过期缓存&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;兜底&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;主解析失败 → 动态获取&lt;/td&gt;
					&lt;td&gt;硬编码区域 → API 拉取&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;核心原则&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;检查对着资源，不是进程名字&lt;/strong&gt;——端口才是冲突点，不是&amp;quot;有没有进程&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对慢变数据，过期缓存比实时查询更合理&lt;/strong&gt;——30 天缓存省 90% 重复调用&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;硬编码永远比数据源旧&lt;/strong&gt;——官方有 API 就别维护表&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;语义操作优先于视觉操作&lt;/strong&gt;——控件树 &amp;gt; 快捷键 &amp;gt; 像素坐标&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;降级链要完整&lt;/strong&gt;——主 → 备 → 缓存，每层失败都有下一层接住&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="总结"&gt;总结
&lt;/h2&gt;&lt;p&gt;运维的终极目标不是&amp;quot;系统永不失败&amp;quot;（不可能），而是：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;系统失败时，有后路可走。&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主代理挂了 → 端口检查防重复，不会雪上加霜&lt;/li&gt;
&lt;li&gt;官方 API 挂了 → 第三方 API + 缓存接住&lt;/li&gt;
&lt;li&gt;硬编码不全 → API 动态拉取兜底&lt;/li&gt;
&lt;li&gt;视觉失灵 → 控件树精准定位&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每一条后路，都是事故发生时的那条&amp;quot;生路&amp;quot;。&lt;strong&gt;给系统留后路，就是给明天的自己留余地。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;本文已脱敏，不含真实域名、IP、UUID 或凭证。&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>