<?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/%E4%B8%80%E8%87%B4%E6%80%A7%E5%93%88%E5%B8%8C/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Mon, 13 Jul 2026 10:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/%E4%B8%80%E8%87%B4%E6%80%A7%E5%93%88%E5%B8%8C/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>Netflix 服务拓扑系统笔记：实时依赖地图是怎么被生产环境捶出来的</title>
      <link>https://ftmao.com/blog/posts/netflix-service-topology-at-scale/</link>
      <pubDate>Mon, 13 Jul 2026 10:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/posts/netflix-service-topology-at-scale/</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/building-service-topology-at-scale-architecture-challenges-and-lessons-learned-f4b792f3f0d8&#34;&gt;Building Service Topology at Scale: Architecture, Challenges, and Lessons Learned&lt;/a&gt;
目标读者：做过或准备做流式数据管线的后端工程师；被 Kafka 消费滞后、JVM GC、热点节点折磨过的人读起来会格外有体感。
阅读目标：搞清楚这套系统的三个核心决策（流式优先、三级聚合管线、动态一致性哈希）各自解决了什么问题，以及 V1 到 V2 连环踩坑的顺序——那个顺序比任何单个方案都值得记住。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;开场白比正文值钱&#34;&gt;〇、开场白比正文值钱&lt;/h2&gt;
&lt;p&gt;这个系列第一篇讲的是 what 和 why：Netflix 工程师需要统一的实时服务依赖视图来加速排障、评估爆炸半径，方案是把 eBPF 网络流、IPC 指标、分布式追踪三个数据源做成物理隔离的三层图。这篇讲的是 how——工程现实。&lt;/p&gt;
&lt;p&gt;作者的开场自白很诚实：&lt;strong&gt;V1 在本地环境完美运行，上生产就是另一个故事&lt;/strong&gt;。Kafka 消费者落后，实例内存耗尽，有的节点流量是其他节点的 100 倍，GC 停顿吃掉的 CPU 比业务逻辑还多。这篇文章不是成功故事，是一趟踩坑复盘。&lt;/p&gt;
&lt;h2 id=&#34;一流式优先新鲜度不是锦上添花&#34;&gt;一、流式优先：新鲜度不是锦上添花&lt;/h2&gt;
&lt;p&gt;传统拓扑系统是批处理：按小时或按天聚合，存全量快照。小规模没问题，但凌晨三点出事故时，一小时前的依赖图是考古，不是可观测性。&lt;/p&gt;
&lt;p&gt;决策是 streaming-first：多区域 Kafka 流和 IPC 指标以 Server-Sent Events 持续摄入，反应式管线处理，拓扑更新延迟在几十分钟量级，对比批处理的小时级、天级。事故响应、变更验证这些场景等不了下一个小时级批次。&lt;/p&gt;
&lt;p&gt;流式处理绕不开一个根本问题：下游慢了怎么办？三个传统方案都不行——无界队列会缓冲到内存爆掉；丢弃式流控会让拓扑残缺，丢的正是连接信息；批处理来不及。他们的答案是&lt;strong&gt;背压&lt;/strong&gt;：Stage 3 写图数据库写不动，通知 Stage 2 减速，Stage 2 通知 Stage 1，Stage 1 让 Kafka consumer 暂停拉取，数据就在 Kafka 里等着。任何一级被打爆（流量尖峰、GC 停顿、外部系统变慢），整条管线自动降到可持续的速率。数据晚到几秒几分钟，但既不丢也不崩。代价是反应式流本身的复杂度，这个后面会还回来。&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;：eBPF 流日志，存图数据库分区。覆盖全，但没有应用上下文。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IPC 层&lt;/strong&gt;：应用指标，存另一个与网络层隔离的图数据库。端点信息丰富，但只覆盖插桩了的服务。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;追踪层&lt;/strong&gt;：分布式追踪，存列式存储（Parquet）。是真实请求路径，但有采样。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;物理隔离的意义是各层可以按自己的吞吐、查询模式和演进节奏独立优化。查询时并行查相关存储再合并结果，做到亚秒延迟。&lt;/p&gt;
&lt;h2 id=&#34;三三级聚合管线一个架构解两个题&#34;&gt;三、三级聚合管线：一个架构解两个题&lt;/h2&gt;
&lt;p&gt;这是全文的核心。网络流日志有个根本缺陷：&lt;strong&gt;它只能看到单个网络跳，看不到应用级连接&lt;/strong&gt;。云环境里流量很少直连，中间隔着负载均衡器、NAT 网关、API 网关、代理。流日志里 App A 到 LB 是一条流，LB 到 App B 是另一条流，但工程师要的是 App A 到 App B 这条逻辑依赖。&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;eBPF 流日志&amp;#34;] --&amp;gt; S1[&amp;#34;Stage 1 初始聚合&amp;lt;br/&amp;gt;过滤非法流&amp;lt;br/&amp;gt;5 分钟时间窗聚合&amp;lt;br/&amp;gt;一致性哈希分发&amp;#34;]
    S1 --&amp;gt;|&amp;#34;SSE 流&amp;#34;| S2[&amp;#34;Stage 2 中间件解析&amp;lt;br/&amp;gt;按中间件分组&amp;lt;br/&amp;gt;双跳拼成直连边&amp;lt;br/&amp;gt;再次一致性哈希&amp;#34;]
    S2 --&amp;gt;|&amp;#34;SSE 流&amp;#34;| S3[&amp;#34;Stage 3 最终聚合与富化&amp;lt;br/&amp;gt;查 KV 补元数据&amp;lt;br/&amp;gt;转成图实体&amp;lt;br/&amp;gt;限流写库&amp;#34;]
    S3 --&amp;gt; DB[&amp;#34;图数据库&amp;#34;]
    S3 -.-&amp;gt;|&amp;#34;背压: 写不动就减速&amp;#34;| S2
    S2 -.-&amp;gt;|&amp;#34;背压传播&amp;#34;| S1
    S1 -.-&amp;gt;|&amp;#34;暂停拉取&amp;lt;br/&amp;gt;数据留在 Kafka&amp;#34;| K
    style S2 fill:#fff3cd&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;三个要点：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么三级而不是一级？数据局部性。&lt;/strong&gt; 要把 App A 到 LB 加 LB 到 App B 拼成 App A 到 App B，必须让同一个中间件的所有流落在同一台实例上做 join。而 Stage 1 里流是按 Kafka 分区散在各实例上的。所以 Stage 2 的关键职能是按中间件标识重新分发——经典 map-reduce：Stage 1 做 map，Stage 2 做 shuffle 加 reduce，Stage 3 做最终聚合。&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 RAW[&amp;#34;解析前 两条单跳流&amp;#34;]
        A1[&amp;#34;App A&amp;#34;] --&amp;gt; LB[&amp;#34;Load Balancer&amp;#34;]
        LB --&amp;gt; B1[&amp;#34;App B&amp;#34;]
    end
    subgraph RES[&amp;#34;解析后 逻辑依赖&amp;#34;]
        A2[&amp;#34;App A&amp;#34;] --&amp;gt;|&amp;#34;合并双跳指标&amp;lt;br/&amp;gt;记录途经的中间件&amp;#34;| B2[&amp;#34;App B&amp;#34;]
    end
    RAW ==&amp;gt;|&amp;#34;按中间件 shuffle 到同一实例&amp;lt;br/&amp;gt;join 入流与出流&amp;#34;| RES
    style RES fill:#e8f5e9&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;为什么三级而不是两级？&lt;/strong&gt; 他们最初就是两级，测试能跑，生产翻车：中间件解析要求把某个热门中间件的所有流集中到一台实例，热点应用的实例成了热节点；而数据富化（查外部存储拿健康状态和元数据）又意味着最忙的实例同时 I/O 最重。拆成三级后，解析（计算密集）和富化持久化（I/O 密集）隔离，每条流被分发、解析、再分发、最后持久化——&lt;strong&gt;负载被两轮哈希打散&lt;/strong&gt;，即使中间件流量是平均值的 100 倍，也没有单实例成为瓶颈。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么 SSE 而不是 gRPC？&lt;/strong&gt; 最初用的 gRPC，结果序列化开销、连接池管理、流式响应的内存压力吃掉的 CPU 比业务逻辑还多。消息队列则白白增加基础设施复杂度。SSE 轻量、HTTP 基础、和反应式流的背压天然集成。教训原话：行业最佳实践不普遍适用，测量，别假设。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么 IPC 层一级就够？&lt;/strong&gt; IPC 指标本来就是应用级的，没有中间件要解析；而且数据从源头就按一致性哈希分对了。这带出一条普适原则：&lt;strong&gt;数据的分区方式决定处理架构&lt;/strong&gt;——进来时分对了就直接聚合，分不对（比如网络流需要中间件解析）就得加 shuffle 级。&lt;/p&gt;
&lt;h2 id=&#34;四动态一致性哈希白嫖现有基础设施&#34;&gt;四、动态一致性哈希：白嫖现有基础设施&lt;/h2&gt;
&lt;p&gt;ASG 动态扩缩容时怎么决定哪个实例收哪个 aggregator？传统做法假设静态集群，扩缩容要显式再平衡、协调服务或手工搬数据。他们的做法：每个实例查服务注册中心拿当前健康的实例列表，排序（保证所有实例视图一致），然后用 &lt;code&gt;findOwnerInstance(aggregator.primaryKey)&lt;/code&gt; 路由。注册中心本来就为健康检查跟踪着 ASG 成员，拿它当集群成员的事实来源，&lt;strong&gt;动态成员资格是白来的&lt;/strong&gt;。一致性哈希保证成员变化时大部分 aggregator 留在原实例，排序列表保证视图一致。扩容时新实例立即接到自己那份流量，部署时 aggregator 无缝漂移到健康实例，全程无协调协议、无人工干预。&lt;/p&gt;
&lt;h2 id=&#34;五v1-的四个坑一个连一个&#34;&gt;五、V1 的四个坑，一个连一个&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;坑一：Kafka 消费滞后。&lt;/strong&gt; lag 从秒涨到分钟再到小时。插桩后发现四个原因：分区数对消费组规模偏少、单次 fetch 拉取记录太少、socket 缓冲区没按吞吐调、跨区域读有额外延迟。对症：加分区、调大每次 fetch 的记录数（拿单条延迟换吞吐）、加大接收缓冲。结果 lag 降到峰值时也在一分钟内。&lt;strong&gt;然后新瓶颈暴露了&lt;/strong&gt;：实例自己吃不下更高的摄入速率——修一个瓶颈必然暴露下一个，这是分布式系统的常态。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;坑二：热点节点与数据放大。&lt;/strong&gt; 最严重的问题。认证、推荐这类热门服务被几百个服务调用，流记录多几个数量级；最初按目的服务做一致性哈希归属，于是拥有热门服务的实例流量是别人的 100 倍。更糟的是洗牌时的数据放大：10 个实例都有本地客户端调某个服务，各自把 aggregator 发给 owner，owner 要合并 10 份。async-profiler 加 heap dump 的结论很清楚：热实例 CPU 大头在 GC，内存压力导致 GC 抖动，抖动吃 CPU，CPU 慢了内存压力更大——恶性循环直到实例宕机，负载转移引发级联故障。解法就是前面那套三级管线：Stage 1 先在内存里做 5 分钟窗口的在线聚合，原始流尽快丢弃被 GC，网络上传的只有压缩后的聚合结果；再经两轮哈希打散。为一个需求（中间件解析）做的架构决策，顺手解了另一个问题（负载不均）——作者说这叫有益的副作用。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;坑三：内存与 GC。&lt;/strong&gt; 修完热点还有高堆占用。原因有三：对象要等 5 分钟窗口攒完、数据在各级间做不必要的类型转换、以及——最有争议的一条——按 Scala 最佳实践用不可变数据结构做 aggregator，每次更新都造新对象，每秒百万记录下垃圾回收器直接被淹没。务实选择：&lt;strong&gt;热路径上改用可变 aggregator&lt;/strong&gt;（别处保持不可变），堆分配降了 50% 以上，GC 停顿从几百毫秒降到几十毫秒。教训：最佳实践是起点不是戒律，要用测量来背书，并且清醒地知道自己交换了什么。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;坑四：反应式流的复杂度。&lt;/strong&gt; Pekko Streams 管线会莫名其妙 stall，没有堆栈可查；&lt;code&gt;.async&lt;/code&gt; 操作符一开始用错，过度并行的流开销大于收益。应对：投入时间真正学懂需求驱动模型、把流图简化为线性流优先、在流边界加监控（缓冲区大小、元素吞吐、背压事件）、团队内部沉淀文档。强力抽象需要投资，别假设自己会了。&lt;/p&gt;
&lt;h2 id=&#34;六v2把能跑的打磨成生产级&#34;&gt;六、V2：把能跑的打磨成生产级&lt;/h2&gt;
&lt;p&gt;V1 解决了架构级问题，V2 是持续优化，模式都一样——生产暴露假设，profiling 定位根因，定点修复：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;aggregator 全程直达&lt;/strong&gt;：之前每级之间都把 aggregator 转成完整图实体，其实下级只需要压缩状态。改为只在 Stage 3 落库前转换一次，砍掉两次中间转换。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;序列化统一 JSON&lt;/strong&gt;：自定义序列化导致难以复现的偶发错误。JSON 比二进制略低效，但人可读让调试容易得多，一致性直接消灭了一整类 bug。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;流参数调优&lt;/strong&gt;：继续调并行度、缓冲区、&lt;code&gt;.async&lt;/code&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;：应用健康、归属等元数据在 Stage 3 落库前补齐，避免查询时的 join 开销。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;七时间旅行任意时刻的拓扑重建&#34;&gt;七、时间旅行：任意时刻的拓扑重建&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;事故发生时调用图长什么样？&amp;ldquo;全量快照存储成本爆炸，事件溯源回放太慢。方案是三件套组合：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;时间窗 aggregator 快照&lt;/strong&gt;：每个 aggregator 带 &lt;code&gt;startTs&lt;/code&gt; 和 &lt;code&gt;endTs&lt;/code&gt;，按 entity_id 加时间戳存进图数据库，相当于每 5 分钟一个检查点。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;属性级变更追踪&lt;/strong&gt;：图数据库只存变化过的属性加时间戳，比全实体拷贝省得多，还提供了窗口边界之内的精度。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;查询时重建&lt;/strong&gt;：查时间范围内的 mutation 历史，按序应用，重建拓扑状态。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;外加一个聪明设计：&lt;strong&gt;查询时再聚合&lt;/strong&gt;复用摄入时的同一套 aggregator 类，可以做没预计算过的任意 groupby 维度（可用性层级、业务域、部署集群），支持探索式分析而不撑爆存储。&lt;/p&gt;
&lt;h2 id=&#34;八原文给的三条通用教训&#34;&gt;八、原文给的三条通用教训&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;规模定性地改变一切&lt;/strong&gt;：每秒 100 次可行的东西在每秒 10 万次失败，变化不是线性的是质变的。不可变结构、单级聚合、gRPC，在小规模下全是对的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一次只优化一个瓶颈&lt;/strong&gt;：修 Kafka lag 暴露热点，修热点暴露 GC，修 GC 暴露序列化。这不是失败，是复杂系统的本性。按影响排序，修透一个再修下一个。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分布是扩展性的关键&lt;/strong&gt;：一致性哈希能分散负载，但挡不住数据本身的幂律分布倾斜。倾斜数据在规模下要多级处理、逐级重新分布。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;工程实践联想&#34;&gt;工程实践联想&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;背压是降级策略，不是性能特性。&lt;/strong&gt; 它的价值不在快，在于&amp;quot;慢了也不死不丢&amp;rdquo;。做异步管线时先想清楚：下游慢了，数据去哪？答案如果是&amp;quot;内存里堆着&amp;quot;或&amp;quot;丢掉&amp;rdquo;，早晚要还。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据分区方式决定架构形状。&lt;/strong&gt; IPC 一级聚合、网络流三级聚合，差异全在数据进来时分没分对。设计管线前先问：处理这个 key 需要的数据，天然在一起吗？不在，就认命加 shuffle 级。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对&amp;quot;最佳实践&amp;quot;保持工程师式的不敬。&lt;/strong&gt; 不可变数据结构、gRPC、二进制序列化，三个正确常识在这套系统里全被推翻了——但每次推翻都有 profiling 数据背书，且范围克制（可变只用于热路径）。违反常识不可怕，凭感觉违反才可怕。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;优化是一条链，不是一次战役。&lt;/strong&gt; 修一个瓶颈暴露下一个，这是吞吐上升的必然结果。所以别指望&amp;quot;性能优化专项&amp;quot;一劳永逸，把 profiling 工具链（async-profiler、heap dump、GC 日志）和边界监控变成日常设施才是正解。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;白嫖现有基础设施是高级的架构品味。&lt;/strong&gt; 拿服务注册中心当集群成员来源，零协调成本拿到动态一致性哈希。新组件引入前先盘一遍手里已有的东西能替代什么——他们连消息队列都因此省掉了。&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;：流式优先加背压（Kafka 当缓冲池，慢下来但不丢不崩）；网络、IPC、追踪三层物理隔离存储，查询时并行合并。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;三级聚合管线&lt;/strong&gt;：Stage 1 时间窗聚合、Stage 2 按中间件 shuffle 并解析双跳、Stage 3 富化持久化。一个设计同时解决中间件解析和热点节点。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;关键妥协&lt;/strong&gt;：热路径可变数据结构（堆分配降 50%+）、gRPC 换 SSE、序列化统一 JSON——全是测量驱动的反常识决策。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;时间旅行&lt;/strong&gt;：窗口快照加属性级 mutation 加查询时重建，任意时刻拓扑可查，还能查询时再聚合做任意维度 groupby。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;方法论&lt;/strong&gt;：规模改变结论；瓶颈是瀑布，修一个露一个；优化是连续过程，测量是唯一指南针。&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/building-service-topology-at-scale-architecture-challenges-and-lessons-learned-f4b792f3f0d8&#34;&gt;Building Service Topology at Scale: Architecture, Challenges, and Lessons Learned&lt;/a&gt;（Netflix TechBlog，作者 Parth Jain、Rakesh Sukumar、Yingwu Zhao、Renzo Sanchez-Silva、Nathan Fisher）。&lt;/li&gt;
&lt;li&gt;文中涉及的关键技术：&lt;a href=&#34;https://pekko.apache.org/&#34;&gt;Apache Pekko&lt;/a&gt;（反应式流实现，Akka fork）、&lt;a href=&#34;https://github.com/async-profiler/async-profiler&#34;&gt;async-profiler&lt;/a&gt;（JVM 采样分析器，热点与 GC 根因定位的主力工具）、&lt;a href=&#34;https://www.reactive-streams.org/&#34;&gt;Reactive Streams&lt;/a&gt;（背压协议规范）。&lt;/li&gt;
&lt;li&gt;系列第一篇介绍多源拓扑的 what 与 why，第三篇将讲追踪层与统一查询，均在 Netflix TechBlog 连载。&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
  </channel>
</rss>
