四道安检门把「超规行李」拦在内存外面(上传预检 / 媒体下载 / XAI 生图 / provider 响应超限);一座储物柜让常用快照免搬运(读快照缓存命中)。拦截与命中,一攻一守都是内存防线。覆盖 m114 · m127 · 后端内存仪表盘「🛡 防护与缓存」组(内存盘 2 图)。
内存防线有一攻一守两件套。守:四道安检门——上传预检、媒体下载、XAI 生图、provider 响应各设大小上限,超规行李直接拒收(rejected_total +1),保护内存不被超大文件击穿。拦截本身=护栏在工作,不是事故;但高频拦截说明上游给的东西异常大,值得查源头。攻后余粮:储物柜——读快照先查缓存,命中就省一次读取(省时省内存);命中率突然崩了=缓存逻辑被改动/失效,读取压力和内存抖动会跟着上来。
先说安检门为什么要存在。图片这东西进门时和拆开后完全两回事:一张几 MB 的 PNG,解码成像素后要占几十 MB 内存;XAI 生图如果用 b64_json 格式返回,图片会被塞进 JSON 文本里,天然比 URL 形态大 33%+。也就是说,不经检查放进来一个「小」文件,内存里可能立刻多出几十个「大」对象——这正是以前内存冲高的经典嫌疑人。所以四个入口各设一道门:用户上传什么、我们从 COS 下载什么、xAI 和 provider 回给我们什么,都先称重,超规就拒收。
看这张图最反直觉的一点:拦截曲线不是坏消息。护栏拦下了超规行李,说明防线在工作、内存保住了——拦一下是设计内的正常行为。真正的坏消息藏在「速率」里:偶尔拦一下无所谓;拦的频率突然持续升高,说明上游开始批量给异常大的东西——要么用户在上传怪文件,要么 provider 悄悄换了默认分辨率。这时候要顺着被哪道门拦的(指标名各不相同)去查源头。
再说储物柜。快照读是很高频的动作,每次都回源读原图,既慢又把读取压力和大对象内存峰值一次次拉起来。所以读快照先查缓存:命中(hit)直接返回,省一次读取;未命中(miss)回源读一次——首次读必 miss,冷启动命中率低属正常。要警惕的是形态突变:命中率一直好好的,某天突然崩了——十有八九是缓存逻辑被改动或失效(发布回归),而不是流量变了。读取压力和内存抖动会紧接着上来。
| 类比里的东西 | 系统里对应的东西 |
|---|---|
| 四道安检门 | 上传预检 / 媒体下载 / XAI 生图 / provider 响应超限,各一道大小上限拦截 |
| 被拒收的超规行李 | siliang_upload_precheck_rejected_total 等四个 rejected_total 计数器(Counter) |
| 安检门的工作日志 | rate(...rejected_total[5m]):看「每秒拦几件」,不看累计总数 |
| 储物柜 | 读快照缓存,按 cache × result 记账(siliang_read_snapshot_cache_total) |
| 行李牌命中,直接取包 | hit:省一次回源读取——省时省内存 |
| 柜子被撬 = 牌子全废 | 命中率突然崩 = 缓存逻辑被改/失效 → 读取压力与内存抖动跟着上来 |
# 数字都来自主图谱字节分布卡(m107/m123 的教训) # 一张几 MB 的 PNG → 解码后几十 MB 内存 # b64_json 塞进 JSON 文本 → 比 URL 形态大 33%+
# 四道门的计数器(主图谱口径,rate 化看速率)
siliang_upload_precheck_rejected_total
siliang_media_download_rejected_total
siliang_xai_image_response_rejected_total
siliang_provider_image_response_rejected_total# 偶发脉冲:设计内行为,不用管 # 持续抬升:上游异常信号,按门查源头 rate(siliang_upload_precheck_rejected_total[5m]) # → 哪道门在拦
# 错: 直接画 _total 累计——永远上扬的直线 # 对: rate(siliang_media_download_rejected_total[5m]) # → 拦截速率
# 主图谱口径:按 cache, result 拆线
sum by (cache, result) (rate(siliang_read_snapshot_cache_total[5m]))# 命中率(形态突变比绝对值重要) sum by (cache) (rate(siliang_read_snapshot_cache_total{result="hit"}[5m])) / clamp_min(sum by (cache) (rate(siliang_read_snapshot_cache_total[5m])), 1)
# 判读口诀 # miss 稳定占比 → 正常 · miss 突然吃掉 hit → 柜子被改了
它是什么:四道安检门各自「每秒拦下几件超规行李」的速率曲线:上传预检 / 媒体下载 / XAI 生图 / provider 响应超限。它们是护栏的工作日志——护栏保护内存不被超大文件击穿,这张图记录它每次出手。
回答什么问题:超大的东西有没有在被拦住?最近上游给的东西是不是变大了、变坏了?(拦截频率就是上游尺寸的「体温计」。)
✅ 健康长啥样:四条线长期贴地,偶发脉冲(个别用户传大文件被拦)后回落;这正是「护栏在工作」的常态。
🚨 危险长啥样:某道门拦截速率持续抬升 = 上游批量给异常大的东西。动作:按门找源头——上传预检高频拦,查用户侧是不是在传怪文件;XAI / provider 门高频拦,对时间戳看字节分布面板(m123),先怀疑上游换了默认分辨率或返回格式(b64 比 URL 大 33%+)。
# 主图谱口径:四道门各一条速率线(Counter → rate)
rate(siliang_upload_precheck_rejected_total[5m])
+ rate(siliang_media_download_rejected_total[5m])
+ rate(siliang_xai_image_response_rejected_total[5m])
+ rate(siliang_provider_image_response_rejected_total[5m])
联动:主图谱 · 上限拦截速率 ↗ · 相关课程:字节分布(对时间戳找膨胀源头) · rate():从里程表算出速度
它是什么:读快照先查缓存(储物柜)的记账本:按 cache × result 看命中形态——哪个缓存、命中(hit)还是没命中(miss)。命中了就省一次回源读取,省时又省内存;miss 则要回源读原图,读取压力和内存峰值都发生在那一侧。
回答什么问题:「读快照」这条高频路径还在被缓存保护着吗?缓存逻辑有没有被最近的发布悄悄改坏?
✅ 健康长啥样:hit 是主流、miss 占比稳定;冷启动或新快照集中读取的时段 miss 偏高、随后回落,属于正常波动。
🚨 危险长啥样:命中率突然崩了 = 缓存逻辑被改动/失效,读取压力和内存抖动会跟着上来。动作:第一反查最近动过缓存/读取路径的发布(这是回归信号,不是流量问题),确认后回滚或修复;别急着「加缓存」。
# 主图谱口径:按 cache × result 拆线看形态
sum by (cache, result) (rate(siliang_read_snapshot_cache_total[5m]))
联动:主图谱 · 读快照缓存命中 ↗ · 相关课程:连接池台账(互链课) · 形态突变判读心法
预检门的拦截速率抬升,可能是个别用户传大文件(无害),也可能是某类客户端在批量传超规文件(要查)。分密度、分维度看。
# 预检门拦截速率(贴地=正常;持续抬升=上游异常) rate(siliang_upload_precheck_rejected_total[5m]) # → 偶发脉冲:个别用户行为,不用管 # → 持续 > 0 的平台:批量超规,值得查源头(哪类文件/哪个入口) # 旁证:被拦说明内存保住了,RSS 不应有对应冲高 max_over_time(siliang_process_resident_memory_bytes[1m]) # → 拦截升高同时 RSS 平稳 = 护栏在正确工作
判读:拦截升、RSS 平 = 护栏立功,去产品侧了解上传行为;拦截升、RSS 也冲高 = 有东西绕过了门,立刻查。
症状:内存午后开始冲高。嫌疑人之一是 provider 生图响应变大(换分辨率/换格式)。把「拦截门」和「字节分布」两张图对时间戳。
# 门 1:provider 响应门有没有在拦 rate(siliang_provider_image_response_rejected_total[5m]) rate(siliang_xai_image_response_rejected_total[5m]) # 门 2:放行进来的响应是不是也变大了(XAI 生图响应字节 P95) histogram_quantile(0.95, sum(rate(siliang_xai_image_response_bytes_bucket[5m])) by (le)) # → P95 抬升 + b64 格式天然比 URL 大 33%+:先怀疑上游换格式/分辨率
判读:拦截没动但字节 P95 抬升 = 放行的东西在变大,内存冲高时间戳对得上即实锤,联系上游或调整门限。
命中率看形态不看绝对值:把 hit 占比画出来,崩塌点几乎总是某次发布。
# 命中率 = hit / (hit + miss),按 cache 拆 sum by (cache) (rate(siliang_read_snapshot_cache_total{result="hit"}[5m])) / clamp_min(sum by (cache) (rate(siliang_read_snapshot_cache_total[5m])), 1) # → 稳定平台=健康;断崖=缓存逻辑被改/失效,第一反查发布 # 告警示例:命中率 10 分钟均值跌破基线一半(示例阈值,按基线调整) - alert: SnapshotCacheHitRateCollapse expr: | sum by (cache) (rate(siliang_read_snapshot_cache_total{result="hit"}[10m])) / clamp_min(sum by (cache) (rate(siliang_read_snapshot_cache_total[10m])), 1) < 0.4 labels: {severity: warning}
内存盘查冲高的通用链路里,这两张图是「排除嫌疑」用的:护栏拦住了吗?缓存还在省读取吗?两个都正常,就把怀疑让给大对象在途(m106/m107)。
# 冲高时刻 T 的两连问 # 问 1:T 附近护栏拦了没有(拦了=超大东西被挡在门外,内存不该涨) rate(siliang_media_download_rejected_total[5m]) # 问 2:T 附近缓存崩了没有(崩了=回源读取暴增,内存抖动跟着来) sum by (result) (rate(siliang_read_snapshot_cache_total[5m])) # 两问都正常 → 转向大对象在途面板(文件/图像模块谁在干活) max_over_time(siliang_file_batch_archive_active[1m])
# 错: increase(…_rejected_total[5m]) > 0 即报 # 护栏天天立功天天挨报 # 对: rate(…_rejected_total[5m]) 持续抬升才升级
# 错: siliang_upload_precheck_rejected_total # 一条只涨的直线 # 对: rate(siliang_upload_precheck_rejected_total[5m])
# 错: sum(rate(所有 rejected_total[5m])) # 只知道"拦了",不知道谁拦 # 对: 每道门单独一条 rate 线,按门定位来源
# 错: hit 率崩 → "再包一层缓存" # 对: hit 率崩 → 对时间戳查发布 → 修复回归
# 错: 重启后 10 分钟 hit 低 → 判定缓存失效 # 对: 看 miss 占比趋势:逐步回落=焐热中;横住不落=真坏了
# 错: 只看 rejected 曲线下结论 # 对: rejected 速率 + histogram_quantile(0.95, …_bytes_bucket) 对照
参考答案:分两层。拦截本身是好消息——护栏把超规行李挡在内存外面,说明防线在工作。但拦截频率持续升高是坏消息的信号:上游开始批量给异常大的东西(用户传怪文件,或 provider 换了分辨率/格式),内存虽然这次保住了,源头值得去查。
参考答案:因为内存按「拆开后」算,不按进门时算。一张几 MB 的 PNG 解码成像素后占几十 MB;XAI 用 b64_json 返回时图片被塞进 JSON 文本,天然比 URL 形态大 33%+。不设门的话,一个「看起来不大」的文件进门就能把内存峰值顶穿——四道门就是在每个入口先称重。
参考答案:第一反应是查最近动过缓存/读取逻辑的发布——命中率长期稳定后突然崩塌,几乎总是缓存逻辑被改动或失效(回归),而不是流量变化。加缓存治不了回归:柜子本身坏了,再买一个柜子还是坏的。正确顺序是修复/回滚,确认命中率回到平台期。