<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>可观测性 on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/%E5%8F%AF%E8%A7%82%E6%B5%8B%E6%80%A7/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Fri, 29 May 2026 10:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/%E5%8F%AF%E8%A7%82%E6%B5%8B%E6%80%A7/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>Netflix 实时服务拓扑图笔记：把「谁依赖谁」从考古变成活地图</title>
      <link>https://ftmao.com/blog/posts/netflix-service-topology-map/</link>
      <pubDate>Fri, 29 May 2026 10:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/netflix-service-topology-map/</guid>
      <description>&lt;h1 id=&#34;netflix-实时服务拓扑图笔记把谁依赖谁从考古变成活地图&#34;&gt;Netflix 实时服务拓扑图笔记：把「谁依赖谁」从考古变成活地图&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;原文：&lt;a href=&#34;https://netflixtechblog.com/from-silos-to-service-topology-why-netflix-built-a-real-time-service-map-0165ba13a7bc&#34;&gt;From Silos to Service Topology: Why Netflix Built a Real-Time Service Map&lt;/a&gt;（Netflix Tech Blog，2026-05-29，作者 Parth Jain 等）
目标读者：维护过微服务系统、半夜被告警叫醒过、对着一堆监控面板猜「到底谁挂了」的后端工程师。
阅读目标：搞清楚 Netflix 为什么认为「依赖关系」值得单独立项做一套系统，三路数据源怎么互补，以及那套「网络中间人解析」管线在解决什么问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一问题信号很多地图没有&#34;&gt;一、问题：信号很多，地图没有&lt;/h2&gt;
&lt;p&gt;原文开场是经典的凌晨三点剧本：工程师被 page 醒，某个关键服务错误率升高，用户观影体验受损。在几千个微服务支撑的系统里，这时候要回答的问题其实非常朴素，但谁也答不快。&lt;/p&gt;
&lt;p&gt;Netflix 做了一件值得学的事：&lt;strong&gt;他们没有拍脑袋立项，而是分析了四年间工程师提交的数千条支持请求&lt;/strong&gt;，发现高频问题惊人地一致：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我的上游和下游依赖是谁？&lt;/li&gt;
&lt;li&gt;这个故障是我自己的问题，还是我依赖的某个服务坏了？&lt;/li&gt;
&lt;li&gt;我下线这台服务做维护，会影响谁？该通知哪些团队？&lt;/li&gt;
&lt;li&gt;为什么这个服务在我的指标里显示为「Unknown」？&lt;/li&gt;
&lt;li&gt;最近我的调用链路上有什么变化，能解释这个行为吗？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;全是依赖问题。而传统可观测性三件套各自只给碎片：指标告诉你症状，日志告诉你单个服务在干嘛，追踪告诉你单次请求怎么流的——&lt;strong&gt;没有一样东西能告诉你稳态下整张依赖网长什么样&lt;/strong&gt;。工程师得在凌晨三点用脑子把多个工具的信息缝起来，慢、易错、压力大。&lt;/p&gt;
&lt;p&gt;这里有个判断很准：缺的不是信号，是&lt;strong&gt;关系&lt;/strong&gt;。信号再多，回答不了「谁连着谁」这种结构性问题。&lt;/p&gt;
&lt;h2 id=&#34;二踩过的坑五条教训&#34;&gt;二、踩过的坑：五条教训&lt;/h2&gt;
&lt;p&gt;Netflix 不是第一次干这件事。原文坦承他们试过外部图数据库、商业平台、各种存储和内部原型，每轮迭代换来一条教训：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;实时性是生死线&lt;/strong&gt;：服务每天部署多次的环境里，几小时前的拓扑图是考古资料，不是可观测性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;规模改变一切&lt;/strong&gt;：能装几千节点的方案，到 Netflix 的服务数量和流量规模会撞墙。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;集成是关键&lt;/strong&gt;：不能要求工程师离开现有工作流去学一套新工具。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据质量差比没有更糟&lt;/strong&gt;：错误或不完整的依赖信息会在事故中把人带向错误结论。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;单一视角讲不全&lt;/strong&gt;：网络连接数据缺应用上下文，应用指标只覆盖做了埋点的服务，必须多源合并。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这五条几乎条条是钱烧出来的，尤其是第四条——&lt;strong&gt;一个会撒谎的地图比没有地图更害人&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&#34;三核心设计三个真相来源三张物理隔离的图&#34;&gt;三、核心设计：三个真相来源，三张物理隔离的图&lt;/h2&gt;
&lt;p&gt;这是全文最有分量的一个架构决策。Netflix 的结论是：&lt;strong&gt;没有任何单一数据源能讲完整的依赖故事&lt;/strong&gt;，所以他们用三路互补的数据各自建一张图：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    subgraph SRC[&amp;#34;三路数据源&amp;#34;]
        EB[&amp;#34;eBPF 网络流&amp;lt;br/&amp;gt;内核态抓真实连接&amp;#34;]
        IPC[&amp;#34;IPC 指标&amp;lt;br/&amp;gt;应用埋点 gRPC GraphQL REST&amp;#34;]
        TR[&amp;#34;端到端追踪&amp;lt;br/&amp;gt;采样后的真实请求路径&amp;#34;]
    end
    subgraph G[&amp;#34;三张物理隔离的图&amp;#34;]
        G1[&amp;#34;网络图&amp;lt;br/&amp;gt;图数据库分区一&amp;lt;br/&amp;gt;覆盖全 但无应用语义&amp;#34;]
        G2[&amp;#34;应用图&amp;lt;br/&amp;gt;图数据库分区二&amp;lt;br/&amp;gt;有端点细节 但只覆盖已埋点服务&amp;#34;]
        G3[&amp;#34;请求图&amp;lt;br/&amp;gt;列式存储&amp;lt;br/&amp;gt;真实行为 但有采样盲区&amp;#34;]
    end
    EB --&amp;gt; G1
    IPC --&amp;gt; G2
    TR --&amp;gt; G3
    G1 --&amp;gt; U[&amp;#34;统一视图&amp;lt;br/&amp;gt;并行查询三路 合并节点与边&amp;lt;br/&amp;gt;亚秒级返回&amp;#34;]
    G2 --&amp;gt; U
    G3 --&amp;gt; U
    style U fill:#e8f5e9&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;三路的价值与短板正好互补：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;eBPF 网络流（网络层）&lt;/strong&gt;：在内核层抓连接记录，&lt;strong&gt;不管应用有没有埋点，每个服务都在图上&lt;/strong&gt;——这是完整性的地基。短板是没有应用上下文：你知道 A 连了 B 的 IP 和协议，但不知道调的是哪个 API 端点。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IPC 指标（应用层）&lt;/strong&gt;：埋点服务发出的进程间通信指标，能看到具体端点、错误率、延迟分布、协议细节。短板是&lt;strong&gt;只覆盖做了埋点的服务&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;端到端追踪（请求层）&lt;/strong&gt;：不是「A 可以调 B」，而是「A 在处理这个具体请求时确实调了 B」，能捕获条件分支和特性开关带来的真实运行时行为。短板是&lt;strong&gt;采样&lt;/strong&gt;——冷门代码路径在聚合视图里可能看不见。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;工程实现上有个细节值得注意：三张图&lt;strong&gt;物理隔离&lt;/strong&gt;——网络层和 IPC 层各在图数据库的一个分区，追踪层用列式存储（为分析型查询优化）。隔离换来两个好处：各层独立演进，查询时可以三路并行、最后合并结果，即使三层全合并也能做到亚秒返回。&lt;/p&gt;
&lt;p&gt;这个设计翻译过来就是一句话：&lt;strong&gt;完整性靠网络流兜底，语义靠 IPC 补齐，行为真实性靠追踪验证&lt;/strong&gt;。任何单源方案都在这三者里缺一角。&lt;/p&gt;
&lt;h2 id=&#34;四数据管线三级聚合与中间人解析&#34;&gt;四、数据管线：三级聚合与「中间人解析」&lt;/h2&gt;
&lt;p&gt;架构层面，流日志从 Kafka 到可查的图要走这样一条管线：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    K[&amp;#34;多区域 Kafka&amp;lt;br/&amp;gt;持续消费流日志&amp;#34;] --&amp;gt; P[&amp;#34;Pekko Streams&amp;lt;br/&amp;gt;分布式处理 自动分区&amp;lt;br/&amp;gt;天然背压&amp;#34;]
    P --&amp;gt; S1[&amp;#34;第一级 初始聚合&amp;lt;br/&amp;gt;从 Kafka 进来的原始流&amp;#34;]
    S1 --&amp;gt; S2[&amp;#34;第二级 中间人解析&amp;lt;br/&amp;gt;识别 LB NAT 网关 代理&amp;lt;br/&amp;gt;把两跳拼回一跳&amp;#34;]
    S2 --&amp;gt; S3[&amp;#34;第三级 最终聚合&amp;lt;br/&amp;gt;叠加健康状态&amp;#34;]
    S3 --&amp;gt; DB[&amp;#34;图数据库&amp;lt;br/&amp;gt;建在分布式 KV 之上&amp;lt;br/&amp;gt;高吞吐多跳遍历&amp;#34;]
    DB --&amp;gt; API[&amp;#34;gRPC API&amp;lt;br/&amp;gt;多跳遍历 按层过滤&amp;lt;br/&amp;gt;分页 亚秒响应&amp;#34;]
    style S2 fill:#fff3cd&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;三个点值得展开：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;处理框架用 Apache Pekko Streams&lt;/strong&gt;（Akka 的 fork），看重的是分布式容错、自动把负载分区到 Auto Scaling Group、以及响应式流自带的背压处理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;三级聚合里最聪明的是第二级&lt;/strong&gt;。网络流日志记录的是逐跳的物理连接：&lt;code&gt;App A → 负载均衡器 → App B&lt;/code&gt;，或者经过 NAT 网关。工程师要的不是这个，是 &lt;code&gt;App A → App B&lt;/code&gt; 这条应用级直连边。第二级负责识别出负载均衡器、NAT 网关、API 网关、代理这些「网络中间人」，把它们的入向流和出向流拼起来，还原出真正的应用到应用路径。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分三级还有个副作用：防热点&lt;/strong&gt;。当某些应用或中间人的流量是其他节点的上百倍时，把聚合分散到多个阶段执行，热点不会压垮单点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;查询侧是 gRPC API：多跳遍历、按可用性等级（Tier 0、Tier 1 之类）和业务域过滤、大结果集分页、亚秒响应。UI 和 API 并重——&lt;strong&gt;工程师用界面排查，自动化系统（韧性框架、爆炸半径计算器、事故响应机器人）走 API&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&#34;五工程师拿到了什么&#34;&gt;五、工程师拿到了什么&lt;/h2&gt;
&lt;p&gt;系统落地后的能力清单，按原文压缩：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;看依赖&lt;/strong&gt;：任意服务的上下游，可按可用性等级和业务域过滤，可切换统一视图或单源视图。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跳信号&lt;/strong&gt;：从图上任意节点直接跳到对应工具的日志、追踪、指标，不用再手动拼服务名和时间窗。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;算爆炸半径&lt;/strong&gt;：下线维护或大改之前，先看清楚影响谁、通知谁、盯什么。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;叠健康状态&lt;/strong&gt;：拓扑上直接叠加哪些服务正在出问题，快速判断「我看到的故障是不是从别处传过来的」。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;程序化查询&lt;/strong&gt;：Platform Modernization 团队用它验证直播关键服务的整条依赖链都打了正确的可用性等级标记——拓扑成了合规校验的数据源。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;时间旅行&lt;/strong&gt;：查历史上某个时间点的拓扑长什么样。实现上没有每个时间片存一份（存储会爆炸），而是用&lt;strong&gt;各层专用的聚合器跨时间窗口累积&lt;/strong&gt;，需要历史视图时再重建。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最后这条「时间旅行」是我觉得最有味道的：事故排查的黄金问题「&lt;strong&gt;故障开始前，我的依赖图变了什么&lt;/strong&gt;」终于被变成一条查询，而不是靠翻部署记录和记忆。&lt;/p&gt;
&lt;h2 id=&#34;六活的地图和下一步&#34;&gt;六、活的地图，和下一步&lt;/h2&gt;
&lt;p&gt;Netflix 反复强调「living map」这个词：新调用关系出现就近实时上图，调用停止的边会从图里淡出，部署改变行为就改变图。关键承诺是——&lt;strong&gt;工程师可以相信图上画的就是现实，而不是某个人对架构的想象&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;路线图上的三件事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;变更事件叠加&lt;/strong&gt;：把部署、配置变更标在拓扑图上，依赖关系和「什么时候改了什么」同框，相关性分析会容易得多。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更丰富的上下文&lt;/strong&gt;：更多端点级细节、协议信息、网络路径信息。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动根因分析&lt;/strong&gt;：一个智能体持续爬拓扑图、跨依赖关联故障、理解历史模式、自动给出疑似根因——&lt;strong&gt;拓扑图是这类智能自动化的知识图谱地基&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;第三条值得划线：他们不是在说「接个 LLM 上去问答」，而是在说「先把依赖关系建成结构化、实时、可查询的图，智能体才有爬的地面」。这个顺序是对的。&lt;/p&gt;
&lt;h2 id=&#34;七工程实践联想&#34;&gt;七、工程实践联想&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;立项之前先做求助记录考古&lt;/strong&gt;。Netflix 拿四年的支持工单说话，高频问题清单就是需求文档。多数内部平台立项靠的是平台团队自己的痛感，而不是用户的——「我觉得你需要」和「数据说你在问」做出来的东西，采纳率天差地别。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;「信号够多」不等于「可观测」&lt;/strong&gt;。指标、日志、追踪三件套回答的都是单点或单次的问题，依赖关系这种结构性知识需要单独建模、单独存储。如果你的团队排查故障还在靠「老张知道这条链路」，那就是缺这一层。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多源互补是处理「讲不全」问题的标准答案&lt;/strong&gt;。任何单一采集手段都有盲区：埋点有覆盖率问题，内核抓包有语义问题，采样有冷门路径问题。与其追求一个完美的源，不如让几个不完美的源互相兜底——这个思路对做 AI Agent 的上下文采集同样成立。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;「中间人解析」是被低估的脏活&lt;/strong&gt;。基础设施里到处是 LB、网关、代理，原始数据永远带着这些噪音。谁能把物理路径还原成逻辑路径，谁的数据才可行动。做链路分析、做 RAG 的数据清洗，都会遇到同构的问题。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;图建好了，Agent 才有事可做&lt;/strong&gt;。Netflix 把自动根因分析放在路线图的末尾而不是开头，因为智能体的前提是有一张实时、准确、可编程查询的图。这对「AI + 运维」的喧嚣是一盆冷水：先修地基，再谈智能。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;本篇小结&#34;&gt;本篇小结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;问题&lt;/strong&gt;：微服务规模下，凌晨三点的工程师回答不了「谁依赖谁、爆炸半径多大、故障源在哪」；四年数千条工单证明这是最痛的缺口。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;方案&lt;/strong&gt;：三路数据源各建一图、物理隔离、并行查询后合并——eBPF 网络流保完整性，IPC 指标保应用语义，分布式追踪保真实行为。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;管线&lt;/strong&gt;：多区域 Kafka → Pekko Streams → 三级聚合（核心是第二级的网络中间人解析，把 LB/NAT/代理的两跳还原成应用级直连边）→ 图数据库（建在分布式 KV 上）→ 亚秒级 gRPC API。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;能力&lt;/strong&gt;：依赖可视化、跳转详细信号、爆炸半径、健康叠加、程序化查询、基于时间窗聚合的历史拓扑（时间旅行）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;哲学&lt;/strong&gt;：过时的拓扑图是考古不是可观测性；地图必须反映现实而非设计文档；单一数据源永远讲不全依赖关系。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;预告&lt;/strong&gt;：这是系列第一篇，下一篇讲规模化落地的工程硬题——Kafka 消费延迟、GC 停顿、响应式流调试、热点治理。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;参考资料&#34;&gt;参考资料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://netflixtechblog.com/from-silos-to-service-topology-why-netflix-built-a-real-time-service-map-0165ba13a7bc&#34;&gt;From Silos to Service Topology: Why Netflix Built a Real-Time Service Map&lt;/a&gt;（Netflix Technology Blog，2026-05-29，原文）&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ebpf.io/&#34;&gt;eBPF 官方文档&lt;/a&gt;（内核态可编程观测技术，网络层数据源的基础）&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://pekko.apache.org/&#34;&gt;Apache Pekko&lt;/a&gt;（Akka 的开源 fork，文中分布式流处理框架）&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://opentelemetry.io/docs/concepts/signals/traces/&#34;&gt;OpenTelemetry Tracing&lt;/a&gt;（分布式追踪的通用概念背景，文中请求层数据源对应物）&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
  </channel>
</rss>
