<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Apache SkyWalking – Performance</title>
    <link>/tags/performance/</link>
    <description>Recent content in Performance on Apache SkyWalking</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Sun, 15 Mar 2026 00:00:00 +0000</lastBuildDate>
    
	  <atom:link href="/tags/performance/feed.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>Zh: AI Coding 如何重塑软件架构师的工作方式</title>
      <link>/zh/2026-03-13-how-ai-changed-the-economics-of-architecture/</link>
      <pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate>
      <guid>/zh/2026-03-13-how-ai-changed-the-economics-of-architecture/</guid>
      <description>
        
        
        &lt;p&gt;&lt;em&gt;以 SkyWalking GraalVM Distro 为例，看 AI Coding 如何把一批探索性 PoC 打磨成一条可重复的迁移流水线。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./graph.jpg&#34; alt=&#34;graph.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;这个项目给我最大的启发，不是 AI 能写多少代码，而是 AI Coding 改变了架构设计的试错成本。当一个想法可以很快做成 PoC、跑起来验证、不行就推翻重来时，架构师就更有机会逼近自己真正想要的设计，而不是过早停在“团队现在做得出来”的折中方案上。&lt;/p&gt;
&lt;p&gt;这种变化在成熟开源系统里尤其重要。Apache SkyWalking OAP 长期以来一直是一个功能强大且经过生产验证的可观测性后端，但大型 Java 平台该有的问题它一个不少：运行时字节码生成、重反射初始化、classpath 扫描、基于 SPI 的模块装配，以及动态 DSL 执行——这些机制方便扩展，但做 GraalVM Native Image 时全是障碍。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SkyWalking GraalVM Distro&lt;/strong&gt; 的出现，源于我们把这个挑战当成一个架构设计问题来处理，而不是一次性的移植工程。目标不仅是让 OAP 能以原生二进制运行，更是把 GraalVM 迁移本身做成一条可重复执行、能够持续跟上上游演进的自动化流水线。&lt;/p&gt;
&lt;p&gt;如果你想看完整的技术设计、基准数据和上手方式，请阅读配套文章：&lt;a href=&#34;/zh/2026-03-13-skywalking-graalvm-distro-design-and-benchmarks/&#34;&gt;SkyWalking GraalVM Distro：设计与基准测试&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&#34;从停滞的想法到可运行的系统&#34;&gt;从停滞的想法到可运行的系统&lt;/h2&gt;
&lt;p&gt;这件事其实很多年前就开始了。在这个仓库创建不久之后，&lt;a href=&#34;https://github.com/yswdqz&#34;&gt;yswdqz&lt;/a&gt; 曾花了数个月探索迁移方案。真正做下来才发现，这个项目远比 GraalVM 文档里列出的那些单点限制复杂得多，这项工作最终也因此搁置了很多年。&lt;/p&gt;
&lt;p&gt;这段停滞很重要。缺少的并不是想法。成熟维护者通常从来不缺想法，真正稀缺的，是把这些想法真正做出来的时间、人力和精力。即使架构师已经看到了几条很有前景的路线，有限的开发资源也会迫使大家更早做出权衡：优先选择实现成本最低的方案，而不是那个更干净、更可复用、更经得起未来变化的方案。&lt;/p&gt;
&lt;p&gt;这种情况非常普遍，并不特殊。在开源社区里，很多工作依赖志愿者或有限的企业赞助；在商业产品里，约束的形式不同，但本质仍然一样：路线图承诺、团队规模和交付压力都会让工程资源始终紧张。在这两种环境里，很多好想法被放弃，并不是因为它们错了，而是因为要把它们真正验证清楚、实现完整，成本太高。&lt;/p&gt;
&lt;p&gt;还有一个同样重要的约束：架构师通常同时也是非常资深的工程师，而不是一个可以全职扑在实现细节上的人。问题在于个人编码精力有限、时间高度碎片化，同时还要在代码尚未出现之前，不断向其他资深工程师解释自己的设计意图。传统上，这种解释主要通过图、文档和沟通完成。它很慢、信息损失大，而且充满不确定性。我们都体验过“传话游戏”：哪怕是很简单的意思，也很容易被误解，而等误解真正暴露出来时，时间已经过去很多了。&lt;/p&gt;
&lt;p&gt;到了 2025 年末，AI Coding 让”同时尝试多条路线”这件事终于变得现实。我们不必再因为实现能力稀缺而过早接受折中，而是可以在多个设计之间来回切换，用代码验证，快速淘汰弱方案，持续迭代，直到架构本身变得足够稳固、足够实用、足够高效。&lt;/p&gt;
&lt;p&gt;这种设计自由度至关重要。GraalVM 文档对单个限制讲得很清楚，但成熟 OSS 平台遇到的是一整套彼此牵连的系统性问题。只修补一个动态机制远远不够。要让 native image 真正落地，我们必须把整类运行时行为改造成构建期产物和自动生成的元数据。&lt;/p&gt;
&lt;p&gt;在这条路的早期历史中，还有一座非常具体的大山。那时上游 SkyWalking 仍然大量依赖 Groovy 来处理 LAL、MAL 和 Hierarchy 脚本。理论上，这只不过是另一个“不支持运行时动态行为”的例子；但在实践中，Groovy 是整条路径上最大的障碍。它不仅意味着脚本执行，还意味着一整套在 JVM 里极其便利、在 native image 里却极其不友好的动态模型。&lt;/p&gt;
&lt;p&gt;为了跨过这道坎，我们围绕 AOT-first 模式重新设计了 OAP 的核心引擎。早期实验必须直接面对 Groovy 时代的运行时行为，并尝试不同的脚本编译方案来绕过去。最终方案走得更远：对齐上游编译器流水线，把动态生成前移到构建期，并引入自动化机制，让这条迁移路径在上游持续演进时依然保持可控。具体来说，就是把 OAL、MAL、LAL 和 Hierarchy 的生成过程变成构建期预编译器的输出，而不是继续保留为启动期的动态行为。&lt;/p&gt;
&lt;h2 id=&#34;ai-coding-如何改写架构迭代&#34;&gt;AI Coding 如何改写架构迭代&lt;/h2&gt;
&lt;p&gt;这次转变的关键，并不只是“写代码更快了”。AI 真正改变的，是想法、原型、验证和重设计之间来回迭代的速度。围绕同一个问题，我们可以很快做出几个可运行的 PoC，迅速淘汰不成立的方向，再把值得保留的抽象慢慢沉淀成一套连贯的迁移系统。&lt;/p&gt;
&lt;p&gt;这并不会削弱人的架构价值，反而会放大它。哪些行为应该前移到构建期，哪些地方应该保留可配置性，哪里应该引入 same-FQCN 替换，如何让上游同步保持可控，以及哪些抽象值得不惜代价保留下来，这些判断仍然只能由人来做。不同的是，AI 的速度让我们终于有机会把这些更好的设计真正做出来，而不是过早退回到更简单、也更差的折中方案。&lt;/p&gt;
&lt;p&gt;这才是软件架构师工作方式真正发生变化的地方。过去，架构师往往已经知道更干净的方向在哪里，但有限的工程产能会逼着那个愿景退回到一个更便宜的妥协方案。现在，架构师在某种意义上又重新变回了“能快速动手的人”：可以直接用代码把思路搭出来，把高层抽象落成接口，再用真实运行的实现去证明设计。&lt;/p&gt;
&lt;p&gt;这不仅改变了实现，也改变了沟通方式。在开源里，我们常说：&lt;code&gt;talk is cheap, show me the code&lt;/code&gt;。在 AI Coding 时代，“把代码拿出来”这件事变得容易多了。设计不再那么依赖一个缓慢的、自上而下的翻译过程：从想法到文档，再到解释，再到实现。代码可以更早出现，也可以更早跑起来。&lt;/p&gt;
&lt;p&gt;这也让其他资深工程师受益。他们不必只靠图、会议或长篇解释来还原整个设计，而是可以直接审查抽象、阅读真实代码、运行它、质疑它，并在具体实现上一起打磨。这让架构协作更快、更清晰，也少了很多沟通误差。&lt;/p&gt;
&lt;p&gt;也正因为如此，我总觉得今天很多 AI 讨论有点跑偏。很多项目确实很有趣、也很好玩，拿来体验当然没问题，但高级工程工作并不会因为“给代码库接了个 agent”就自然变好。真正重要的，不是哪个 demo 看起来最炫，而是哪些工程能力真的被放大了，同时软件开发本身的纪律有没有被保留下来。&lt;/p&gt;
&lt;p&gt;对于架构师和资深工程师来说，这里真正重要的能力包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;快速做对比式原型验证&lt;/strong&gt;：不是只用 slides 和文档去论证某个想法，而是直接把多个方案做成可运行代码来比较。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;大规模代码理解能力&lt;/strong&gt;：能在大量模块之间快速阅读，同时保持对整个系统的全局认识。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;系统性的重构能力&lt;/strong&gt;：把基于反射、依赖运行时动态行为的路径，系统性地改造成适配 AOT 约束的设计。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;搭建自动化的能力&lt;/strong&gt;：当一个迁移步骤在每次上游同步时都必须重做一次，靠手工处理本身就很费时费力，而且越往后只会越累。AI 让我们真正有条件去投资生成器、清单、一致性检查和漂移检测，把重复的人力劳动变成可重复的自动化流程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;大范围审查能力&lt;/strong&gt;：在很大的代码面上检查边界条件、兼容性约束，以及方案是否经得起反复执行。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些能力也都体现在最终的设计结果里。same-FQCN 替换为 GraalVM 特定行为建立了清晰、受控的边界；反射元数据不再依赖手工维护的猜测清单，而是直接从构建产物中生成；各种清单机制和漂移检测，则把原本模糊的“上游同步风险”变成了显式的工程工作流。&lt;/p&gt;
&lt;p&gt;对于初级工程师，我觉得这里的启发同样重要。AI 不会让架构设计、系统约束、接口设计、测试和可维护性这些基本功变得不重要。恰恰相反，这些能力只会变得更重要，因为它们决定了“被加速的实现”最终产出的是一个可持续演进的系统，还是只是更快地制造出更多代码。真正的杠杆来自工程判断力，而不是新鲜感。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; 和 &lt;strong&gt;Gemini AI&lt;/strong&gt; 在整个过程中都扮演了工程加速器的角色。在 GraalVM Distro 这个项目里，它们具体帮我们做了几件事：&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;：把不适合运行时的模式系统性替换成 AOT 友好的实现方式。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;让上游同步真正可持续&lt;/strong&gt;：每次 distro 从上游 SkyWalking 拉取变更后，元数据扫描、配置再生成和重新编译都必须再来一次。AI 帮助我们把这些过程做成流水线，使每次同步都变成一个可控、且大部分自动化的过程，而不是一次比一次更长的手工重复劳动。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;在大范围内审查逻辑和边界情况&lt;/strong&gt;：特别是在功能对等性比纯实现速度更重要的地方。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最终产出的，不只是一次大重写，而是一套可重复的系统：预编译器、manifest 驱动的加载、反射配置生成、替换边界，以及让上游迁移可审查、可自动化的漂移检测机制。&lt;/p&gt;
&lt;p&gt;如果你想看这种开发方法背后的更广泛背景，可以读这篇文章：&lt;a href=&#34;/zh/2026-03-08-agentic-vibe-coding/&#34;&gt;在成熟开源大型项目中实践 Agentic Vibe Coding：软件工程与工程控制论还在延续&lt;/a&gt;。这篇文章则是这个故事的下一步：不仅是在一个成熟代码库里增强功能，而是重新激活一项曾经停滞的工作，并把它真正做成可运行系统。&lt;/p&gt;
&lt;h2 id=&#34;真正改变的到底是什么&#34;&gt;真正改变的到底是什么&lt;/h2&gt;
&lt;p&gt;这个项目最重要的结果，并不是一张 benchmark 表。基准数据当然属于 distro 本身，而且它们很重要，因为它们证明这套系统是真实可运行的。但对这篇文章来说，更深层的变化发生在方法论层面：AI Coding 改变了我们探索、验证和打磨架构方案的方式。&lt;/p&gt;
&lt;p&gt;过去，架构往往更像一项以文档为主、后面拖着漫长而昂贵实现过程的活动。现在，我们可以更快地在想法、原型、比较和重设计之间切换。这让我们真正有机会去追求更高抽象层次的方案，保留更干净的边界，并建设那些让迁移过程可持续维护的自动化机制。&lt;/p&gt;
&lt;p&gt;这项工作的技术证据，就是 SkyWalking GraalVM Distro 本身：它不仅是一个可运行的系统，更是一条由预编译器、自动生成的反射元数据、受控替换边界和漂移检查组成的迁移流水线。基准数据之所以重要，是因为它们证明这套系统在实践里是成立的；但从架构角度看，真正的结果是：这次迁移不再是一场一次性的移植，而是变成了一套可重复执行的系统工程。关于完整测试方法、原始数据和技术设计，请阅读配套文章：&lt;a href=&#34;/zh/2026-03-13-skywalking-graalvm-distro-design-and-benchmarks/&#34;&gt;SkyWalking GraalVM Distro：设计与基准测试&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;项目仓库位于 &lt;a href=&#34;https://github.com/apache/skywalking-graalvm-distro&#34;&gt;apache/skywalking-graalvm-distro&lt;/a&gt;。我们欢迎社区成员测试这个新发行版、提交 issue，并帮助它逐步走向生产可用。&lt;/p&gt;
&lt;p&gt;对我来说，更深层的启发并不止于这个发行版。AI Coding 不会让架构变得不重要，反而会让架构更值得被认真追求。当实现速度提升到一定程度时，我们终于有机会在真实代码里验证更多想法，保留那些真正好的抽象，并把那些过去常常因为投入太大而半途妥协的系统真正做出来。&lt;/p&gt;
&lt;p&gt;对于资深工程师来说，瓶颈正在从单纯的代码实现速度，转向品味、系统判断力，以及定义稳定边界的能力。对于初级工程师来说，真正该走的路不是追逐每一种看上去都很刺激的 AI 工作流，而是把基础能力练得更扎实，让加速真正产生复利：理解需求、阅读陌生系统、质疑假设，并识别出在系统快速变化时仍然必须保持正确的那些部分。AI Coding 降低了验证好设计的代价，但并没有降低工程判断本身的门槛。&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Zh: SkyWalking GraalVM Distro：设计与基准测试</title>
      <link>/zh/2026-03-13-skywalking-graalvm-distro-design-and-benchmarks/</link>
      <pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate>
      <guid>/zh/2026-03-13-skywalking-graalvm-distro-design-and-benchmarks/</guid>
      <description>
        
        
        &lt;p&gt;&lt;em&gt;这篇文章会完整介绍我们如何把 Apache SkyWalking OAP 迁移到 GraalVM Native Image。目标不是做一次性移植，而是把这件事做成一套能持续跟上上游演进的流程。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./graph.jpg&#34; alt=&#34;graph.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;如果你想看这项工作的更大背景，以及 AI Coding 如何让这个项目真正做得出来，请阅读：&lt;a href=&#34;/zh/2026-03-13-how-ai-changed-the-economics-of-architecture/&#34;&gt;AI Coding 如何重塑软件架构师的工作方式&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&#34;为什么-graalvm-在这里是刚需&#34;&gt;为什么 GraalVM 在这里是刚需&lt;/h2&gt;
&lt;p&gt;GraalVM Native Image 可以把 Java 应用做 Ahead-of-Time（AOT）编译，生成独立可执行文件。对于像 SkyWalking OAP 这样的可观测性后端来说，这不是“锦上添花”的性能优化，而是明确的工程刚需。&lt;/p&gt;
&lt;p&gt;可观测性平台必须是基础设施中最可靠的部分。它必须在自己要观测的那些故障发生时依然存活。在云原生环境里，工作负载会不断扩缩容、迁移和重启，负责观测一切的后端本身不能还是那个启动慢、空闲占用大、恢复缓慢的重型进程。&lt;/p&gt;
&lt;p&gt;我们的基准测试结果让这个结论变得非常具体：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;**启动时间：**约 5 ms 对比约 635 ms。在 Kubernetes 集群里，当 OAP Pod 被驱逐或重新调度时，635 ms 的差距意味着这段时间里的遥测数据可能会丢失。5 ms 的情况下，新 Pod 往往在大部分客户端还没感知到中断之前就已经重新开始接收数据了。&lt;/li&gt;
&lt;li&gt;**空闲内存：**约 41 MiB 对比约 1.2 GiB。可观测性后端是 24/7 常驻运行的。在多租户或边缘部署场景里，基础 RSS 降了 97%，可以放进更小的节点，而不再必须占用一台专用机器。&lt;/li&gt;
&lt;li&gt;**负载下内存：**在 20 RPS 下约 629 MiB 对比约 2.0 GiB。生产级负载下内存降了 70%，直接对应更少的节点、更低的云账单，以及在后端本身成为扩容瓶颈之前更多的余量。&lt;/li&gt;
&lt;li&gt;**没有预热惩罚：**峰值吞吐可以更早发挥出来。JVM 的 JIT 编译器往往需要数分钟流量才能完成热点优化，在这段时间里，尾延迟更差，数据处理也会滞后。原生二进制没有同样的阶段。&lt;/li&gt;
&lt;li&gt;**更小的攻击面：**不再需要完整 JDK 运行时，需要跟踪和修补的 CVE 也就少了很多。对于一个会接收整个集群所有服务数据的组件来说，这一点很重要。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些都不是“小修小补”。它们直接改变了哪些部署形态开始变得可行：无服务器形态的可观测性后端、边车式采集模型、内存预算极其紧张的边缘节点。只有当后端足够轻、足够快时，这些方案才真正有落地空间。&lt;/p&gt;
&lt;h2 id=&#34;挑战一个成熟动态特性很多的-java-平台&#34;&gt;挑战：一个成熟、动态特性很多的 Java 平台&lt;/h2&gt;
&lt;p&gt;SkyWalking OAP 身上有大型 Java 平台的所有典型问题：运行时字节码生成、重反射初始化、classpath 扫描、基于 SPI 的模块装配，以及动态 DSL 执行。这些机制方便扩展，但做 GraalVM native image 时全是障碍。&lt;/p&gt;
&lt;p&gt;GraalVM 文档中列出的限制，只是问题的开始。在一个成熟的 OSS 平台里，这些限制会深深缠绕在多年积累下来的运行时设计决策中。常规的 GraalVM native image 很难处理运行时类生成、反射、动态发现和脚本执行，而这些在 SkyWalking OAP 中都不是零散存在的，它们本来就是系统设计的一部分。&lt;/p&gt;
&lt;p&gt;在这个发行版的早期历史里，还有一座非常具体的大山。那时上游 SkyWalking 仍然高度依赖 Groovy 来处理 LAL、MAL 和 Hierarchy 脚本。理论上，它只是另一个“不支持运行时动态”的组件；但在实践里，Groovy 是整条路径上最大的障碍。它不仅仅是脚本执行问题，而是代表着一整套在 JVM 世界里极其便利、在 native image 世界里极其不友好的动态模型。&lt;/p&gt;
&lt;h2 id=&#34;设计目标让迁移这件事可以重复做&#34;&gt;设计目标：让迁移这件事可以重复做&lt;/h2&gt;
&lt;p&gt;设计目标不是”把 native-image 跑通一次就完”，而是做出一套能反复用、能长期维护的迁移系统：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;把运行时生成的产物前移到构建期。&lt;/strong&gt; OAL、MAL、LAL、Hierarchy 规则，以及 meter 相关的生成类，都在构建期完成编译并打包，而不是等到启动时才动态生成。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用确定性的加载机制替代动态发现。&lt;/strong&gt; classpath 扫描和运行时注册路径被转换为基于 manifest 的加载方式。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;减少运行时反射，并在构建期生成 native 元数据。&lt;/strong&gt; 反射配置不再依赖人工维护的猜测清单，而是根据真实 manifest 和扫描结果生成。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;让上游同步边界保持清晰。&lt;/strong&gt; same-FQCN replacements 会被显式打包、列清单，并通过陈旧性检查守住边界。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;让变化第一时间暴露出来。&lt;/strong&gt; 一旦上游 provider、规则文件或被替换的源文件发生变化，测试就会失败，迫使我们做显式审查。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这才是最关键的架构转变。好的抽象和前瞻性，在 AI 时代并没有变得不重要，反而变得更重要了，因为它们决定了 AI 带来的速度，最终产出的是一个可维护的系统，还是一堆膨胀得更快的代码。&lt;/p&gt;
&lt;h2 id=&#34;把运行时动态行为变成构建期产物&#34;&gt;把运行时动态行为变成构建期产物&lt;/h2&gt;
&lt;p&gt;SkyWalking OAP 里有多个在 JVM 世界里很自然、但在 native image 里很棘手的动态子系统：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OAL 会在运行时生成类。&lt;/li&gt;
&lt;li&gt;LAL、MAL 和 Hierarchy 在历史上与大量基于 Groovy 的运行时行为绑定在一起，这也是早期 distro 工作中最难处理的阻碍之一。&lt;/li&gt;
&lt;li&gt;MAL、LAL 和 Hierarchy 规则依赖运行时编译行为。&lt;/li&gt;
&lt;li&gt;基于 Guava 的 classpath 扫描会发现注解、dispatcher、decorator 和 meter function。&lt;/li&gt;
&lt;li&gt;基于 SPI 的模块和 provider 发现依赖更动态的运行时环境。&lt;/li&gt;
&lt;li&gt;YAML/config 初始化和框架集成依赖反射访问。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在 SkyWalking GraalVM Distro 里，这些问题不是靠零散补丁一个个修掉的，而是被统一收敛到一条构建期流水线里。&lt;/p&gt;
&lt;p&gt;预编译器会在构建过程中运行 DSL 引擎、导出生成类、写入 manifest、序列化配置数据，并生成 native-image 元数据。这样一来，启动时只需要做类加载和注册，不再需要运行时代码生成。运行期之所以能变得更简单，是因为原本的复杂性被前移到了构建期。&lt;/p&gt;
&lt;p&gt;这也是为什么这个项目不只是一次性能优化。我们的设计目标，是把复杂性前移到一个更容易验证、更容易自动化、也更便于反复执行的位置。&lt;/p&gt;
&lt;h2 id=&#34;same-fqcn-替换一条可控的边界&#34;&gt;same-FQCN 替换：一条可控的边界&lt;/h2&gt;
&lt;p&gt;这个发行版里最实用的设计选择之一，就是使用 same-FQCN 替换类。我们没有依赖模糊的启动技巧，也没有依赖未文档化的加载顺序假设。相反，我们会重新打包 GraalVM 特定 jar，排除原本的上游类，再让替换类占据完全相同的 fully-qualified class name。&lt;/p&gt;
&lt;p&gt;这对可维护性非常关键，因为它建立了一条非常清晰的边界：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上游类仍然定义行为契约；&lt;/li&gt;
&lt;li&gt;GraalVM 侧的替换类提供兼容的实现策略；&lt;/li&gt;
&lt;li&gt;打包过程则让这次替换变得显式可见。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如，OAL 的加载过程从运行时编译变成了基于 manifest 的预编译类加载。类似的替换也处理了 MAL 和 LAL DSL 加载、模块装配、配置初始化，以及多个对反射敏感的路径。目标不是把一切都 fork 出去，而是只替换那些运行时模型从根本上不适合 native image 的部分。&lt;/p&gt;
&lt;p&gt;随后，这条边界还会通过测试来守护：测试会对照与 replacement 对应的上游源文件做哈希。当上游改动了这些文件中的任何一个，构建就会失败，并明确告诉我们哪个 replacement 需要重新审查。这样一来，“如何跟上上游”就不再是一个充满焦虑的抽象问题，而变成一项明确、可落地的工程工作。&lt;/p&gt;
&lt;h2 id=&#34;反射配置不是猜出来的而是生成出来的&#34;&gt;反射配置不是猜出来的，而是生成出来的&lt;/h2&gt;
&lt;p&gt;在很多 GraalVM 迁移项目里，&lt;code&gt;reflect-config.json&lt;/code&gt; 最终会变成一个靠经验不断累积的工件。它会越来越大，越来越陈旧，最后没有人真正清楚它是不是完整，也不清楚每一项配置为什么存在。这种模式在一个持续演化的大型 OSS 平台里是无法扩展的。&lt;/p&gt;
&lt;p&gt;在这个发行版里，反射元数据直接从构建产物和扫描结果中生成，包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OAL、MAL、LAL、Hierarchy 以及 meter 生成类的 manifest；&lt;/li&gt;
&lt;li&gt;注解扫描得到的类；&lt;/li&gt;
&lt;li&gt;Armeria HTTP handler；&lt;/li&gt;
&lt;li&gt;GraphQL resolver 和 schema 映射类型；&lt;/li&gt;
&lt;li&gt;被接受的 &lt;code&gt;ModuleConfig&lt;/code&gt; 类。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这是一种健康得多的模式。我们不再依赖人去记住所有可能触发反射访问的路径，而是让系统根据真实迁移流水线推导出反射元数据。构建过程本身，成为了事实来源。&lt;/p&gt;
&lt;h2 id=&#34;让上游同步变得现实可行&#34;&gt;让上游同步变得现实可行&lt;/h2&gt;
&lt;p&gt;如果这个发行版只是一次性的工程冲刺，那它的意义会小很多。真正困难的事情，是在上游 SkyWalking 继续演进的同时，让它还能持续维护下去。&lt;/p&gt;
&lt;p&gt;这也是为什么仓库里会有一整套显式的清单和漂移检测机制：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;provider 清单，用来强制新上游 provider 被分类；&lt;/li&gt;
&lt;li&gt;规则文件清单，用来强制新 DSL 输入被显式确认；&lt;/li&gt;
&lt;li&gt;预编译 YAML 输入的 SHA watcher；&lt;/li&gt;
&lt;li&gt;带 GraalVM 特定 replacement 的上游源文件 SHA watcher。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;好的抽象不仅仅是代码结构优雅，更在于你是否选择了一种能在未来变化面前继续成立的迁移设计。&lt;/p&gt;
&lt;h2 id=&#34;基准测试结果&#34;&gt;基准测试结果&lt;/h2&gt;
&lt;p&gt;我们在一台 Apple M3 Max（macOS、Docker Desktop、10 CPUs / 62.7 GB）上，对标准 JVM OAP 和 GraalVM Distro 做了对比测试，两者都连接到 BanyanDB。&lt;/p&gt;
&lt;h3 id=&#34;启动测试docker-compose无流量3-次取中位数&#34;&gt;启动测试（Docker Compose，无流量，3 次取中位数）&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;指标&lt;/th&gt;
          &lt;th&gt;JVM OAP&lt;/th&gt;
          &lt;th&gt;GraalVM OAP&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;/td&gt;
          &lt;td&gt;635 ms&lt;/td&gt;
          &lt;td&gt;5 ms&lt;/td&gt;
          &lt;td&gt;约快 127 倍&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;热启动时间&lt;/td&gt;
          &lt;td&gt;630 ms&lt;/td&gt;
          &lt;td&gt;5 ms&lt;/td&gt;
          &lt;td&gt;约快 126 倍&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;空闲 RSS&lt;/td&gt;
          &lt;td&gt;约 1.2 GiB&lt;/td&gt;
          &lt;td&gt;约 41 MiB&lt;/td&gt;
          &lt;td&gt;约降低 97%&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;启动时间的测量方式，是从 OAP 第一条应用日志时间戳开始，到出现 &lt;code&gt;listening on 11800&lt;/code&gt; 日志（即 gRPC 服务 ready）为止。&lt;/p&gt;
&lt;h3 id=&#34;持续负载下kind--istio-1252--bookinfo约-20-rps2-个-oap-副本&#34;&gt;持续负载下（Kind + Istio 1.25.2 + Bookinfo，约 20 RPS，2 个 OAP 副本）&lt;/h3&gt;
&lt;p&gt;在 60 秒预热之后，每 10 秒采样一次，共 30 个样本。&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;指标&lt;/th&gt;
          &lt;th&gt;JVM OAP&lt;/th&gt;
          &lt;th&gt;GraalVM OAP&lt;/th&gt;
          &lt;th&gt;差异&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CPU 中位数（millicores）&lt;/td&gt;
          &lt;td&gt;101&lt;/td&gt;
          &lt;td&gt;68&lt;/td&gt;
          &lt;td&gt;-33%&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CPU 平均值（millicores）&lt;/td&gt;
          &lt;td&gt;107&lt;/td&gt;
          &lt;td&gt;67&lt;/td&gt;
          &lt;td&gt;-37%&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;内存中位数（MiB）&lt;/td&gt;
          &lt;td&gt;2068&lt;/td&gt;
          &lt;td&gt;629&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;-70%&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;内存平均值（MiB）&lt;/td&gt;
          &lt;td&gt;2082&lt;/td&gt;
          &lt;td&gt;624&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;-70%&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;两个版本报告的 entry-service CPM 一致，说明在这个测试负载下，两者的流量处理能力相同。&lt;/p&gt;
&lt;p&gt;我们每 30 秒通过 swctl 对所有已发现服务收集这些指标：
&lt;code&gt;service_cpm&lt;/code&gt;、&lt;code&gt;service_resp_time&lt;/code&gt;、&lt;code&gt;service_sla&lt;/code&gt;、&lt;code&gt;service_apdex&lt;/code&gt;、&lt;code&gt;service_percentile&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;完整的基准测试脚本和原始数据位于发行版仓库中的 &lt;a href=&#34;https://github.com/apache/skywalking-graalvm-distro/tree/main/benchmark&#34;&gt;benchmark/&lt;/a&gt; 目录。&lt;/p&gt;
&lt;h2 id=&#34;当前状态&#34;&gt;当前状态&lt;/h2&gt;
&lt;p&gt;这个项目已经是一个可运行的实验性发行版，托管在独立仓库中：&lt;a href=&#34;https://github.com/apache/skywalking-graalvm-distro&#34;&gt;apache/skywalking-graalvm-distro&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;当前发行版有意聚焦在一种现代、高性能的运行模式上：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;存储：&lt;/strong&gt; BanyanDB&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;集群模式：&lt;/strong&gt; Standalone 和 Kubernetes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配置方式：&lt;/strong&gt; 无配置或 Kubernetes ConfigMap&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;运行模型：&lt;/strong&gt; 固定模块集合、预编译产物和 AOT 友好的装配方式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这种聚焦是刻意的。要把迁移做成一套可重复的系统，第一步必须先把边界收清楚，做出一个真正能跑起来的版本，然后再在不失控的前提下逐步扩展。&lt;/p&gt;
&lt;h2 id=&#34;快速开始&#34;&gt;快速开始&lt;/h2&gt;
&lt;p&gt;由于 SkyWalking GraalVM Distro 的设计目标就是追求极致性能，它目前最适合与 &lt;strong&gt;BanyanDB&lt;/strong&gt; 存储后端搭配使用。当前发布的镜像已经可以在 Docker Hub 获取，你可以直接用下面这个 &lt;code&gt;docker-compose.yml&lt;/code&gt; 启动整套系统。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;version&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;services&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;banyandb&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;image&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;ghcr.io/apache/skywalking-banyandb:e1ba421bd624727760c7a69c84c6fe55878fb526&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;container_name&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;banyandb&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;restart&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;always&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;ports&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;- &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;17912:17912&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;- &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;17913:17913&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;command&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;standalone --stream-root-path /tmp/stream-data --measure-root-path /tmp/measure-data --measure-metadata-cache-wait-duration 1m --stream-metadata-cache-wait-duration 1m&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;healthcheck&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;test&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;sh&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;nc -nz 127.0.0.1 17912&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;interval&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;5s&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;timeout&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;10s&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;retries&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;120&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;oap&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;image&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;apache/skywalking-graalvm-distro:0.1.1&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;container_name&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;oap&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;depends_on&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;banyandb&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;condition&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;service_healthy&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;restart&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;always&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;ports&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;- &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;11800:11800&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;- &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;12800:12800&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;environment&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;SW_STORAGE&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;banyandb&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;SW_STORAGE_BANYANDB_TARGETS&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;banyandb:17912&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;SW_HEALTH_CHECKER&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;default&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;healthcheck&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;test&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;CMD-SHELL&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;nc -nz 127.0.0.1 11800 || exit 1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;interval&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;5s&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;timeout&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;10s&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;retries&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;120&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;ui&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;image&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;ghcr.io/apache/skywalking/ui:10.3.0&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;container_name&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;ui&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;depends_on&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;oap&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;condition&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;service_healthy&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;restart&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;always&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;ports&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;- &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;8080:8080&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;environment&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;SW_OAP_ADDRESS&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;http://oap:12800&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;只需要执行：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;欢迎社区来测试这个新发行版、提交 issue，并帮助我们推动它走向生产可用。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;特别感谢 GraalVM 团队提供的技术基础。&lt;/em&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Blog: How AI Changed the Economics of Architecture</title>
      <link>/blog/2026-03-13-how-ai-changed-the-economics-of-architecture/</link>
      <pubDate>Fri, 13 Mar 2026 00:00:00 +0000</pubDate>
      <guid>/blog/2026-03-13-how-ai-changed-the-economics-of-architecture/</guid>
      <description>
        
        
        &lt;p&gt;&lt;em&gt;SkyWalking GraalVM Distro: A case study in turning runnable PoCs into a repeatable migration pipeline.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./graph.jpg&#34; alt=&#34;graph.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;The most important lesson from this project is not that AI can generate a large amount of code. It is that AI changes the economics of architecture. When runnable PoCs become cheap to build, compare, discard, and rebuild, architects can push further toward the design they actually want instead of stopping early at a compromise they can afford to implement.&lt;/p&gt;
&lt;p&gt;That shift matters a lot in mature open source systems. Apache SkyWalking OAP has long been a powerful and production-proven observability backend, but it also carries all the realities of a large Java platform: runtime bytecode generation, reflection-heavy initialization, classpath scanning, SPI-based module wiring, and dynamic DSL execution that are friendly to extensibility but hostile to GraalVM native image.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SkyWalking GraalVM Distro&lt;/strong&gt; is the result of treating that challenge as a design-system problem instead of a one-off porting exercise. The goal was not only to make OAP run as a native binary, but to turn GraalVM migration itself into a repeatable automation pipeline that can stay aligned with upstream evolution.&lt;/p&gt;
&lt;p&gt;For the full technical design, benchmark data, and getting-started guide, see the companion post: &lt;a href=&#34;../2026-03-13-skywalking-graalvm-distro-design-and-benchmarks/index.md&#34;&gt;SkyWalking GraalVM Distro: Design and Benchmarks&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;from-paused-idea-to-runnable-system&#34;&gt;From Paused Idea to Runnable System&lt;/h2&gt;
&lt;p&gt;This journey actually began years ago. Shortly after this repository was created, &lt;a href=&#34;https://github.com/yswdqz&#34;&gt;yswdqz&lt;/a&gt; spent several months exploring the transition. The project proved much harder in practice than the individual GraalVM limitations sounded on paper, and the work eventually paused for years.&lt;/p&gt;
&lt;p&gt;That pause is important. The missing ingredient was not ideas. Mature maintainers usually have more ideas than time. The real constraint was implementation economics. Even when the architect can see several promising directions, limited developer resources force an earlier trade-off: choose the path that is cheapest to implement, not necessarily the path that is cleanest, most reusable, or most future-proof.&lt;/p&gt;
&lt;p&gt;This is a very common reality, not an exceptional one. In open source communities, much of the work depends on volunteers or limited company sponsorship. In commercial products, the pressure is different but the constraint is still real: roadmap commitments, staffing limits, and delivery deadlines keep engineering resources tight. In both worlds, good ideas are often abandoned not because they are wrong, but because they are too expensive to validate and implement thoroughly.&lt;/p&gt;
&lt;p&gt;There is another constraint that matters just as much: the architect is usually also a very senior engineer, not a full-time implementation machine. That means limited personal coding energy, fragmented time, and a constant need to explain ideas to other senior engineers before the code exists. Traditionally, that explanation happens through diagrams, documents, and conversations. It is slow, lossy, and unpredictable. We all know some version of the Telephone Game: even simple words are easy to misunderstand, and by the time the misunderstanding becomes visible, a lot of time has already passed.&lt;/p&gt;
&lt;p&gt;What changed in late 2025 was that AI engineering made multiple runnable ideas affordable. Instead of picking an early compromise because implementation capacity was scarce, we could switch repeatedly between designs, validate them with code, discard weak directions quickly, and keep iterating until the architecture became solid, practical, and efficient enough to hold.&lt;/p&gt;
&lt;p&gt;That design freedom was critical. GraalVM documentation gives clear guidance on isolated limitations, but a mature OSS platform hits them as a connected system. Fixing only one dynamic mechanism is not enough. To make native image practical, we had to turn whole categories of runtime behavior into build-time artifacts and automated metadata generation.&lt;/p&gt;
&lt;p&gt;There was also a very concrete mountain in front of us in the early history of this distro. In the first several commits of the repository, upstream SkyWalking still relied heavily on Groovy for LAL, MAL, and Hierarchy scripts. In theory, that was just one more unsupported runtime-heavy component. In practice, Groovy was the biggest obstacle in the whole path. It represented not only script execution, but a whole dynamic model that was deeply convenient on the JVM side and deeply unfriendly to native image.&lt;/p&gt;
&lt;p&gt;To bridge the gap, we re-architected the core engines of OAP around an AOT-first model. Earlier experiments had to confront Groovy-era runtime behavior directly and explore alternative script-compilation approaches to get around it. The finalized direction went further: align with the upstream compiler pipeline, move dynamic generation to build time, and add automation so the migration stays controllable as upstream keeps moving. Concretely, that meant turning OAL, MAL, LAL, and Hierarchy generation into build-time precompiler outputs instead of leaving them as startup-time dynamic behavior.&lt;/p&gt;
&lt;h2 id=&#34;ai-speed-changed-the-design-loop&#34;&gt;AI Speed Changed the Design Loop&lt;/h2&gt;
&lt;p&gt;The scale of this transformation was not only about coding faster. AI changed the loop between idea, prototype, validation, and redesign. We could build runnable PoCs for different approaches, throw away weak ones quickly, and preserve the promising abstractions until they formed a coherent migration system.&lt;/p&gt;
&lt;p&gt;That does not reduce the role of human architecture. It raises the value of it. Human judgment was still required to decide what should become build-time, what should stay configurable, where to introduce same-FQCN replacements, how to keep upstream sync controllable, and which abstractions were worth preserving. But AI speed made it realistic to pursue those better designs instead of settling for a simpler compromise too early.&lt;/p&gt;
&lt;p&gt;This is the real change in the economics of architecture. In the past, an architect might already know the cleaner direction, but limited engineering capacity often forced that vision back toward a cheaper compromise. Now the architect can return much closer to being a fast developer again: building code, shaping high-abstraction interfaces, and using design patterns to prove the vision directly in the real world.&lt;/p&gt;
&lt;p&gt;That changes communication as much as implementation. In open source, we often say, &lt;code&gt;talk is cheap, show me the code&lt;/code&gt;. With AI engineering, showing the code becomes much more straightforward. The design no longer depends so heavily on a slow top-down translation from idea to documents to interpretation to implementation. The code can appear earlier, and it can run earlier.&lt;/p&gt;
&lt;p&gt;Other senior engineers benefit from this too. They do not need to reconstruct the whole design only from diagrams, meetings, or long explanations. They can review the actual abstraction, see the behavior in code, run it, challenge it, and refine it from something concrete. That makes architectural collaboration faster, clearer, and less lossy.&lt;/p&gt;
&lt;p&gt;This is also where I think the current AI discussion is often noisy. Many projects are fun, surprising, and worth exploring, but advanced engineering work is not improved merely by attaching an agent to a codebase. The important question is not which demo looks most magical. The important question is which engineering capabilities are actually being accelerated without losing the discipline of software development itself.&lt;/p&gt;
&lt;p&gt;For architects and senior engineers, the capabilities that mattered most here were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fast comparative prototyping:&lt;/strong&gt; Building several runnable approaches in code instead of defending one idea with slides and documents.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Large-scale code comprehension:&lt;/strong&gt; Reading across many modules quickly enough to keep the whole system in view.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Systematic refactoring:&lt;/strong&gt; Converting reflection-heavy or runtime-dynamic paths into designs that fit AOT constraints.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation construction:&lt;/strong&gt; When a migration step must be repeated every upstream sync, doing it manually once is already expensive. Doing it manually again next time is even more expensive. AI made it practical to invest in generators, inventories, consistency checks, and drift detectors that turn repeated manual work into repeatable automation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Review at breadth:&lt;/strong&gt; Checking edge cases, compatibility boundaries, and repeatability across a large surface area.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those capabilities were visible in the resulting design. Same-FQCN replacements created a controlled boundary for GraalVM-specific behavior. Reflection metadata was generated from build outputs instead of maintained as a hand-written guess list. Inventories and drift detectors turned upstream sync from a vague maintenance risk into an explicit engineering workflow.&lt;/p&gt;
&lt;p&gt;For junior engineers, I think the lesson is equally important. AI does not remove the need to learn architecture, invariants, interfaces, testing, or maintenance. It makes those skills more valuable, because they determine whether accelerated implementation produces a durable system or just more code faster. The leverage comes from engineering judgment, not from novelty.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt; and &lt;strong&gt;Gemini AI&lt;/strong&gt; acted as engineering accelerators throughout this process. In the GraalVM Distro specifically, they helped us:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Explore migration strategies as running code:&lt;/strong&gt; Instead of debating which approach might work, we built and compared multiple real prototypes, discarded the weak ones, and kept what held up.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Refactor reflection-heavy and dynamic code paths:&lt;/strong&gt; Replace runtime-hostile patterns with AOT-friendly alternatives across the codebase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make upstream sync sustainable:&lt;/strong&gt; Every time the distro pulls from upstream SkyWalking, metadata scanning, config regeneration, and recompilation must happen again. AI helped build the pipeline so that each sync is a controlled, largely automated process rather than a fresh manual effort that grows longer each time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Review logic and edge cases at scale:&lt;/strong&gt; Especially in places where feature parity mattered more than raw implementation speed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The result was not just a large rewrite. It was a repeatable system: precompilers, manifest-driven loading, reflection-config generation, replacement boundaries, and drift detectors that make upstream migration reviewable and automatable.&lt;/p&gt;
&lt;p&gt;For the broader methodology behind this style of development, see &lt;a href=&#34;https://builder.aws.com/content/3AgtzlikuD9bSUJrWDCjGW5Q5nW/agentic-vibe-coding-in-a-mature-oss-project-what-worked-what-didnt&#34;&gt;Agentic Vibe Coding in a Mature OSS Project&lt;/a&gt;. This post is the next step in that story: not only enhancing an active mature codebase, but reviving a paused effort and making it actually runnable.&lt;/p&gt;
&lt;h2 id=&#34;what-actually-changed&#34;&gt;What Actually Changed&lt;/h2&gt;
&lt;p&gt;The most important outcome of this project is not a benchmark table. The benchmark results belong to the distro itself, and they matter because they prove the system is real. But for this post, the deeper result is methodological: AI engineering changed how architecture could be explored, validated, and refined.&lt;/p&gt;
&lt;p&gt;Instead of treating architecture as a mostly document-driven activity followed by a long and expensive implementation phase, we were able to move much faster between idea, prototype, comparison, and redesign. That made it realistic to pursue higher-abstraction solutions, preserve cleaner boundaries, and build the automation needed to keep the migration maintainable over time.&lt;/p&gt;
&lt;p&gt;The technical evidence for that work is the SkyWalking GraalVM Distro itself: not only a runnable system, but a migration pipeline expressed as precompilers, generated reflection metadata, controlled replacement boundaries, and drift checks. The benchmark data matter because they prove the system works in practice, but the architectural result is that the migration became a repeatable system rather than a one-time port. For detailed benchmark methodology, per-pod data, and the full technical design, see &lt;a href=&#34;https://skywalking.apache.org/blog/2026-03-13-how-ai-changed-the-economics-of-architecture/&#34;&gt;SkyWalking GraalVM Distro: Design and Benchmarks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The project is hosted at &lt;a href=&#34;https://github.com/apache/skywalking-graalvm-distro&#34;&gt;apache/skywalking-graalvm-distro&lt;/a&gt;. We invite the community to test it, report issues, and help move it toward production readiness.&lt;/p&gt;
&lt;p&gt;For me, the deeper takeaway is broader than this distro. AI engineering does not make architecture less important. It makes architecture more worth pursuing. When implementation speed rises enough, we can afford to test more ideas in code, keep the good abstractions, and build systems that would previously have been judged too expensive to finish well.&lt;/p&gt;
&lt;p&gt;For senior engineers, that means the bottleneck shifts away from raw typing speed and toward taste, system judgment, and the ability to define stable boundaries. For junior engineers, it means the path forward is not to chase every exciting AI workflow, but to become stronger at the fundamentals that let acceleration compound: understanding requirements, reading unfamiliar systems, questioning assumptions, and recognizing what must remain correct as everything around it changes. AI changed the economics of architecture because it lowered the cost of validating better designs without lowering the bar for engineering judgment.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Blog: SkyWalking GraalVM Distro: Design and Benchmarks</title>
      <link>/blog/2026-03-13-skywalking-graalvm-distro-design-and-benchmarks/</link>
      <pubDate>Fri, 13 Mar 2026 00:00:00 +0000</pubDate>
      <guid>/blog/2026-03-13-skywalking-graalvm-distro-design-and-benchmarks/</guid>
      <description>
        
        
        &lt;p&gt;&lt;em&gt;A technical deep-dive into how we migrated Apache SkyWalking OAP to GraalVM Native Image — not as a one-off port, but as a repeatable pipeline that stays aligned with upstream.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./graph.jpg&#34; alt=&#34;graph.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;For the broader story of how AI engineering made this project economically viable, see &lt;a href=&#34;/blog/2026-03-13-how-ai-changed-the-economics-of-architecture/&#34;&gt;How AI Changed the Economics of Architecture&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;why-graalvm-is-not-optional&#34;&gt;Why GraalVM Is Not Optional&lt;/h2&gt;
&lt;p&gt;GraalVM Native Image compiles Java applications Ahead-of-Time (AOT) into standalone executables. For an observability backend like SkyWalking OAP, this is not a performance optimization — it is an operational necessity.&lt;/p&gt;
&lt;p&gt;An observability platform must be the most reliable component in the infrastructure. It has to survive the failures it is supposed to observe. In cloud-native environments where workloads scale, migrate, and restart constantly, the backend that watches everything cannot itself be the slow, heavy process that takes seconds to recover and gigabytes to idle.&lt;/p&gt;
&lt;p&gt;Our benchmarks make the case concrete:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Startup:&lt;/strong&gt; ~5 ms vs ~635 ms. In a Kubernetes cluster where an OAP pod gets evicted or rescheduled, a 635 ms gap means lost telemetry — traces, metrics, and logs that arrive during that window are simply dropped. At 5 ms, the new pod is receiving data before most clients even notice the disruption.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Idle memory:&lt;/strong&gt; ~41 MiB vs ~1.2 GiB. Observability backends run 24/7. In a multi-tenant or edge deployment, a 97% reduction in baseline RSS is the difference between fitting the observability stack on a small node and needing a dedicated one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory under load:&lt;/strong&gt; ~629 MiB vs ~2.0 GiB at 20 RPS. A 70% reduction at production-like traffic means fewer nodes, lower cloud bills, and more headroom before the backend itself becomes a scaling bottleneck.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No warm-up penalty:&lt;/strong&gt; Peak throughput is available from the first request. The JVM&amp;rsquo;s JIT compiler needs minutes of traffic before it optimizes hot paths — during that window, tail latency is worse and data processing lags behind. A native binary has no such phase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smaller attack surface:&lt;/strong&gt; No JDK runtime means fewer CVEs to track and patch. For a component that ingests data from every service in the cluster, that matters.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are not incremental improvements. They change what deployment topologies are practical. Serverless observability backends, sidecar-model collectors, edge nodes with tight memory budgets — all become realistic when the backend is this light and this fast.&lt;/p&gt;
&lt;h2 id=&#34;the-challenge-a-mature-dynamic-java-platform&#34;&gt;The Challenge: A Mature, Dynamic Java Platform&lt;/h2&gt;
&lt;p&gt;SkyWalking OAP carries all the realities of a large Java platform: runtime bytecode generation, reflection-heavy initialization, classpath scanning, SPI-based module wiring, and dynamic DSL execution. These patterns are friendly to extensibility but hostile to GraalVM native image.&lt;/p&gt;
&lt;p&gt;The documented GraalVM limitations are only the beginning. In a mature OSS platform, those limitations are deeply entangled with years of runtime design decisions. Standard GraalVM native images struggle with runtime class generation, reflection, dynamic discovery, and script execution — all of which had deep roots in SkyWalking OAP.&lt;/p&gt;
&lt;p&gt;There was also a very concrete mountain in the early history of this distro. Upstream SkyWalking relied heavily on Groovy for LAL, MAL, and Hierarchy scripts. In theory, that was just one more unsupported runtime-heavy component. In practice, Groovy was the biggest obstacle in the whole path. It represented not only script execution, but a whole dynamic model that was deeply convenient on the JVM side and deeply unfriendly to native image.&lt;/p&gt;
&lt;h2 id=&#34;the-design-goal-make-migration-repeatable&#34;&gt;The Design Goal: Make Migration Repeatable&lt;/h2&gt;
&lt;p&gt;The final design is not just &amp;ldquo;run native-image successfully.&amp;rdquo; It is a system that keeps migration work repeatable:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pre-compile runtime-generated assets at build time.&lt;/strong&gt; OAL, MAL, LAL, Hierarchy rules, and meter-related generated classes are compiled during the build and packaged as artifacts instead of being generated at startup.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replace dynamic discovery with deterministic loading.&lt;/strong&gt; Classpath scanning and runtime registration paths are converted into manifest-driven loading.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduce runtime reflection and generate native metadata from the build.&lt;/strong&gt; Reflection configuration is produced from actual manifests and scanned classes instead of being maintained as a hand-written guess list.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep the upstream sync boundary explicit.&lt;/strong&gt; Same-FQCN replacements are intentionally packaged, inventoried, and guarded with staleness checks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make drift visible immediately.&lt;/strong&gt; If upstream providers, rule files, or replaced source files change, tests fail and force explicit review.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That is the architectural shift that matters most. Reusable abstraction and foresight did not become less important in the AI era. They became more important, because they determine whether AI speed produces a maintainable system or just a fast-growing pile of code.&lt;/p&gt;
&lt;h2 id=&#34;turning-runtime-dynamism-into-build-time-assets&#34;&gt;Turning Runtime Dynamism into Build-Time Assets&lt;/h2&gt;
&lt;p&gt;SkyWalking OAP has several dynamic subsystems that are natural in a JVM world but problematic for native image:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OAL generates classes at runtime.&lt;/li&gt;
&lt;li&gt;LAL, MAL, and Hierarchy were historically tied to Groovy-heavy runtime behavior, which became one of the biggest practical blockers in the early distro work.&lt;/li&gt;
&lt;li&gt;MAL, LAL, and Hierarchy rules depend on runtime compilation behavior.&lt;/li&gt;
&lt;li&gt;Guava-based classpath scanning discovers annotations, dispatchers, decorators, and meter functions.&lt;/li&gt;
&lt;li&gt;SPI-based module/provider discovery expects a more dynamic runtime environment.&lt;/li&gt;
&lt;li&gt;YAML/config initialization and framework integrations depend on reflective access.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In SkyWalking GraalVM Distro, these are not solved one by one as isolated patches. They are pulled into a build-time pipeline.&lt;/p&gt;
&lt;p&gt;The precompiler runs the DSL engines during the build, exports generated classes, writes manifests, serializes config data, and generates native-image metadata. That means startup becomes class loading and registration, not runtime code generation. The runtime path is simpler because the build path became richer.&lt;/p&gt;
&lt;p&gt;This is also why the project is more than a performance exercise. The design goal was to move complexity into a place where it is easier to verify, easier to automate, and easier to repeat.&lt;/p&gt;
&lt;h2 id=&#34;same-fqcn-replacements-as-a-controlled-boundary&#34;&gt;Same-FQCN Replacements as a Controlled Boundary&lt;/h2&gt;
&lt;p&gt;One of the most practical design choices in this distro is the use of same-FQCN replacement classes. We do not rely on vague startup tricks or undocumented ordering assumptions. Instead, the GraalVM-specific jars are repackaged so the original upstream classes are excluded and the replacement classes occupy the exact same fully-qualified names.&lt;/p&gt;
&lt;p&gt;This matters for maintainability. It creates a very clear boundary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the upstream class still defines the behavior contract,&lt;/li&gt;
&lt;li&gt;the GraalVM replacement provides a compatible implementation strategy,&lt;/li&gt;
&lt;li&gt;and the packaging makes that swap explicit.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, OAL loading changes from runtime compilation into manifest-driven loading of precompiled classes. Similar replacements handle MAL and LAL DSL loading, module wiring, config initialization, and several reflection-sensitive paths. The goal is not to fork everything. The goal is to replace only the places where the runtime model is fundamentally unfriendly to native image.&lt;/p&gt;
&lt;p&gt;That boundary is then guarded by tests that hash the upstream source files corresponding to the replacements. When upstream changes one of those files, the build fails and tells us exactly which replacement needs review. This is what turns &amp;ldquo;keeping up with upstream&amp;rdquo; from an anxiety problem into a visible engineering task.&lt;/p&gt;
&lt;h2 id=&#34;reflection-config-is-generated-not-guessed&#34;&gt;Reflection Config Is Generated, Not Guessed&lt;/h2&gt;
&lt;p&gt;In many GraalVM migrations, &lt;code&gt;reflect-config.json&lt;/code&gt; becomes a manually accumulated artifact. It grows over time, gets stale, and nobody is fully sure whether it is complete or why each entry exists. That approach does not scale well for a large, evolving OSS platform.&lt;/p&gt;
&lt;p&gt;In this distro, reflection metadata is generated from the build outputs and scanned classes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;manifests for OAL, MAL, LAL, Hierarchy, and meter-generated classes,&lt;/li&gt;
&lt;li&gt;annotation-scanned classes,&lt;/li&gt;
&lt;li&gt;Armeria HTTP handlers,&lt;/li&gt;
&lt;li&gt;GraphQL resolvers and schema-mapped types,&lt;/li&gt;
&lt;li&gt;and accepted &lt;code&gt;ModuleConfig&lt;/code&gt; classes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a much healthier model. Instead of asking people to remember every reflective access path, the system derives reflection metadata from the actual migration pipeline. The build becomes the source of truth.&lt;/p&gt;
&lt;h2 id=&#34;keeping-upstream-sync-practical&#34;&gt;Keeping Upstream Sync Practical&lt;/h2&gt;
&lt;p&gt;If this distro were only a one-time engineering sprint, it would be much less interesting. The real challenge is keeping it alive while upstream SkyWalking continues to evolve.&lt;/p&gt;
&lt;p&gt;That is why the repo includes explicit inventories and drift detectors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;provider inventories that force new upstream providers to be categorized,&lt;/li&gt;
&lt;li&gt;rule-file inventories that force new DSL inputs to be acknowledged,&lt;/li&gt;
&lt;li&gt;SHA watchers for precompiled YAML inputs,&lt;/li&gt;
&lt;li&gt;and SHA watchers for upstream source files with GraalVM-specific replacements.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Good abstraction is not only about elegant code structure. It is about choosing a migration design that can survive contact with future change.&lt;/p&gt;
&lt;h2 id=&#34;benchmark-results&#34;&gt;Benchmark Results&lt;/h2&gt;
&lt;p&gt;We benchmarked the standard JVM OAP against the GraalVM Distro on an Apple M3 Max (macOS, Docker Desktop, 10 CPUs / 62.7 GB), both connecting to BanyanDB.&lt;/p&gt;
&lt;h3 id=&#34;boot-test-docker-compose-no-traffic-median-of-3-runs&#34;&gt;Boot Test (Docker Compose, no traffic, median of 3 runs)&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Metric&lt;/th&gt;
          &lt;th&gt;JVM OAP&lt;/th&gt;
          &lt;th&gt;GraalVM OAP&lt;/th&gt;
          &lt;th&gt;Delta&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Cold boot startup&lt;/td&gt;
          &lt;td&gt;635 ms&lt;/td&gt;
          &lt;td&gt;5 ms&lt;/td&gt;
          &lt;td&gt;~127x faster&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Warm boot startup&lt;/td&gt;
          &lt;td&gt;630 ms&lt;/td&gt;
          &lt;td&gt;5 ms&lt;/td&gt;
          &lt;td&gt;~126x faster&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Idle RSS&lt;/td&gt;
          &lt;td&gt;~1.2 GiB&lt;/td&gt;
          &lt;td&gt;~41 MiB&lt;/td&gt;
          &lt;td&gt;~97% reduction&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Boot time is measured from OAP&amp;rsquo;s first application log timestamp to the &lt;code&gt;listening on 11800&lt;/code&gt; log line (gRPC server ready).&lt;/p&gt;
&lt;h3 id=&#34;under-sustained-load-kind--istio-1252--bookinfo-at-20-rps-2-oap-replicas&#34;&gt;Under Sustained Load (Kind + Istio 1.25.2 + Bookinfo at ~20 RPS, 2 OAP replicas)&lt;/h3&gt;
&lt;p&gt;30 samples at 10s intervals after 60s warmup.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Metric&lt;/th&gt;
          &lt;th&gt;JVM OAP&lt;/th&gt;
          &lt;th&gt;GraalVM OAP&lt;/th&gt;
          &lt;th&gt;Delta&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CPU median (millicores)&lt;/td&gt;
          &lt;td&gt;101&lt;/td&gt;
          &lt;td&gt;68&lt;/td&gt;
          &lt;td&gt;-33%&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CPU avg (millicores)&lt;/td&gt;
          &lt;td&gt;107&lt;/td&gt;
          &lt;td&gt;67&lt;/td&gt;
          &lt;td&gt;-37%&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Memory median (MiB)&lt;/td&gt;
          &lt;td&gt;2068&lt;/td&gt;
          &lt;td&gt;629&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;-70%&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Memory avg (MiB)&lt;/td&gt;
          &lt;td&gt;2082&lt;/td&gt;
          &lt;td&gt;624&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;-70%&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Both variants reported identical entry-service CPM, confirming equivalent traffic processing capability.&lt;/p&gt;
&lt;p&gt;Service metrics collected every 30s via swctl for all discovered services:
&lt;code&gt;service_cpm&lt;/code&gt;, &lt;code&gt;service_resp_time&lt;/code&gt;, &lt;code&gt;service_sla&lt;/code&gt;, &lt;code&gt;service_apdex&lt;/code&gt;, &lt;code&gt;service_percentile&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Full benchmark scripts and raw data are in the &lt;a href=&#34;https://github.com/apache/skywalking-graalvm-distro/tree/main/benchmark&#34;&gt;benchmark/&lt;/a&gt; directory of the distro repository.&lt;/p&gt;
&lt;h2 id=&#34;current-status&#34;&gt;Current Status&lt;/h2&gt;
&lt;p&gt;The project is a runnable experimental distribution, hosted in its own repository: &lt;a href=&#34;https://github.com/apache/skywalking-graalvm-distro&#34;&gt;apache/skywalking-graalvm-distro&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The current distro intentionally focuses on a modern, high-performance operating model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Storage:&lt;/strong&gt; BanyanDB&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cluster modes:&lt;/strong&gt; Standalone and Kubernetes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration:&lt;/strong&gt; none or Kubernetes ConfigMap&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Runtime model:&lt;/strong&gt; fixed module set, precompiled assets, and AOT-friendly wiring&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This focus is deliberate. A repeatable migration system starts by making a clear scope runnable, then expanding without losing control.&lt;/p&gt;
&lt;h2 id=&#34;getting-started&#34;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;Because the SkyWalking GraalVM Distro is designed for peak performance, it is optimized to work with &lt;strong&gt;BanyanDB&lt;/strong&gt; as its storage backend. The current published image is available on Docker Hub, and you can boot the stack using the following &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;version&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;services&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;banyandb&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;image&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;ghcr.io/apache/skywalking-banyandb:e1ba421bd624727760c7a69c84c6fe55878fb526&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;container_name&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;banyandb&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;restart&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;always&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;ports&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;- &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;17912:17912&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;- &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;17913:17913&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;command&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;standalone --stream-root-path /tmp/stream-data --measure-root-path /tmp/measure-data --measure-metadata-cache-wait-duration 1m --stream-metadata-cache-wait-duration 1m&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;healthcheck&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;test&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;sh&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;-c&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;nc -nz 127.0.0.1 17912&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;interval&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;5s&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;timeout&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;10s&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;retries&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;120&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;oap&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;image&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;apache/skywalking-graalvm-distro:0.1.1&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;container_name&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;oap&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;depends_on&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;banyandb&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;condition&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;service_healthy&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;restart&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;always&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;ports&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;- &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;11800:11800&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;- &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;12800:12800&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;environment&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;SW_STORAGE&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;banyandb&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;SW_STORAGE_BANYANDB_TARGETS&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;banyandb:17912&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;SW_HEALTH_CHECKER&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;default&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;healthcheck&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;test&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;CMD-SHELL&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;nc -nz 127.0.0.1 11800 || exit 1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;interval&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;5s&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;timeout&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;10s&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;retries&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;120&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;ui&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;image&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;ghcr.io/apache/skywalking/ui:10.3.0&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;container_name&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;ui&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;depends_on&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;oap&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;condition&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;service_healthy&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;restart&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;always&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;ports&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;- &lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#34;8080:8080&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;environment&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;SW_OAP_ADDRESS&lt;/span&gt;&lt;span style=&#34;color:#1f2328&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#fff&#34;&gt; &lt;/span&gt;http://oap:12800&lt;span style=&#34;color:#fff&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Simply run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We invite the community to test this new distribution, report issues, and help us move it toward a production-ready state.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Special thanks to the GraalVM team for the technology foundation.&lt;/em&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Blog: Diagnose Service Mesh Network Performance with eBPF</title>
      <link>/blog/diagnose-service-mesh-network-performance-with-ebpf/</link>
      <pubDate>Tue, 27 Sep 2022 00:00:00 +0000</pubDate>
      <guid>/blog/diagnose-service-mesh-network-performance-with-ebpf/</guid>
      <description>
        
        
        &lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;This article will show how to use &lt;a href=&#34;https://github.com/apache/skywalking&#34;&gt;Apache SkyWalking&lt;/a&gt; with &lt;a href=&#34;https://ebpf.io/what-is-ebpf/&#34;&gt;eBPF&lt;/a&gt; to make network troubleshooting easier in a service mesh environment.&lt;/p&gt;
&lt;p&gt;Apache SkyWalking is an application performance monitor tool for distributed systems. It observes metrics, logs, traces, and events in the service mesh environment and uses that data to generate a dependency graph of your pods and services. This dependency graph can provide quick insights into your system, especially when there&amp;rsquo;s an issue.&lt;/p&gt;
&lt;p&gt;However, when troubleshooting network issues in SkyWalking&amp;rsquo;s service topology, it is not always easy to pinpoint where the error actually is. There are two reasons for the difficulty:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Traffic through the Envoy sidecar is not easy to observe.&lt;/strong&gt; Data from Envoy&amp;rsquo;s &lt;a href=&#34;https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/accesslog/v3/als.proto&#34;&gt;Access Log Service (ALS)&lt;/a&gt; shows traffic between services (sidecar-to-sidecar), but not metrics on communication between the Envoy sidecar and the service it proxies. Without that information, it is more difficult to understand the impact of the sidecar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;There is a lack of data from transport layer (OSI Layer 4) communication.&lt;/strong&gt; Since services generally use application layer (OSI Layer 7) protocols such as HTTP, observability data is generally restricted to application layer communication. However, the root cause may actually be in the transport layer, which is typically opaque to observability tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Access to metrics from Envoy-to-service and transport layer communication can make it easier to diagnose service issues. To this end, SkyWalking needs to collect and analyze transport layer metrics between processes inside Kubernetes pods - a task well suited to eBPF. We investigated using eBPF for this purpose and present our results and
a demo below.&lt;/p&gt;
&lt;h2 id=&#34;monitoring-kubernetes-networks-with-ebpf&#34;&gt;Monitoring Kubernetes Networks with eBPF&lt;/h2&gt;
&lt;p&gt;With its origins as the Extended Berkeley Packet Filter, eBPF is a general purpose mechanism for injecting and running your own code into the Linux kernel and is an excellent tool for monitoring network traffic in Kubernetes Pods. In the next few sections, we&#39;ll provide an overview of how to use eBPF for network monitoring as background for introducing &lt;a href=&#34;https://github.com/apache/skywalking-rover&#34;&gt;Skywalking Rover&lt;/a&gt;, a metrics collector and profiler powered by eBPF to diagnose CPU and network performance.&lt;/p&gt;
&lt;h3 id=&#34;how-applications-and-the-network-interact&#34;&gt;How Applications and the Network Interact&lt;/h3&gt;
&lt;p&gt;Interactions between the application and the network can generally be
divided into the following steps from higher to lower levels of
abstraction:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;f0.svg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;User Code:&lt;/strong&gt; Application code uses high-level network libraries in the application stack to exchange data across the network, like sending and receiving HTTP requests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network Library:&lt;/strong&gt; When the network library receives a network request, it interacts with the language API to send the network data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language API:&lt;/strong&gt; Each language provides an API for operating the network, system, etc. When a request is received, it interacts with the system API. In Linux, this API is called syscalls.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Linux API:&lt;/strong&gt; When the Linux kernel receives the request through the API, it communicates with the socket to send the data, which is usually closer to an OSI Layer 4 protocol, such as TCP, UDP, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Socket Ops:&lt;/strong&gt; Sending or receiving the data to/from the NIC.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Our hypothesis is that eBPF can monitor the network. There are two ways
to implement the interception: &lt;strong&gt;User space (uprobe)&lt;/strong&gt; or &lt;strong&gt;Kernel space
(kprobe)&lt;/strong&gt;. The table below summarizes the differences.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;/th&gt;
          &lt;th&gt;Pros&lt;/th&gt;
          &lt;th&gt;Cons&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;uprobe&lt;/td&gt;
          &lt;td&gt;•	Get more application-related contexts, such as whether the current request is HTTP or HTTPS.&lt;/br&gt;•	Requests and responses can be intercepted by a single method&lt;/td&gt;
          &lt;td&gt;•	Data structures can be unstable, so it is more difficult to get the desired data. &lt;/br&gt; •	Implementation may differ between language/library versions. &lt;/br&gt; •	Does not work in applications without &lt;a href=&#34;https://en.wikipedia.org/wiki/Symbol_table&#34;&gt;symbol tables&lt;/a&gt;.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;kprobe&lt;/td&gt;
          &lt;td&gt;•	Available for all languages. &lt;/br&gt; •	The data structure and methods are stable and do not require much adaptation. &lt;/br&gt; •	Easier correlation with underlying data, such as getting the destination address of TCP, OSI Layer 4 protocol metrics, etc.&lt;/td&gt;
          &lt;td&gt;•	A single request and response may be split into multiple probes. &lt;/br&gt; •	Contextual information is not easy to get for stateful requests. For example header compression in HTTP/2.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For the general network performance monitor, we chose to use the kprobe (intercept the syscalls) for the following reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It&amp;rsquo;s available for applications written in any programming language, and it&amp;rsquo;s stable, so it saves a lot of development/adaptation costs.&lt;/li&gt;
&lt;li&gt;It can be correlated with metrics from the system level, which makes it easier to troubleshoot.&lt;/li&gt;
&lt;li&gt;As a single request and response are split into multiple probes, we can use technology to correlate them.&lt;/li&gt;
&lt;li&gt;For contextual information, It&amp;rsquo;s usually used in OSI Layer 7 protocol network analysis. So, if we just monitor the network performance, then they can be ignored.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;kprobes-and-network-monitoring&#34;&gt;Kprobes and network monitoring&lt;/h3&gt;
&lt;p&gt;Following the &lt;a href=&#34;http://linasm.sourceforge.net/docs/syscalls/network.php&#34;&gt;network syscalls of Linux documentation&lt;/a&gt;, we can implement network monitoring by intercepting two types of methods: &lt;strong&gt;socket operations&lt;/strong&gt; and &lt;strong&gt;send/receive&lt;/strong&gt; methods.&lt;/p&gt;
&lt;h4 id=&#34;socket-operations&#34;&gt;Socket Operations&lt;/h4&gt;
&lt;p&gt;When accepting or connecting with another socket, we can get the
following information:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Connection information&lt;/strong&gt;: Includes the remote address from the connection which helps us to understand which pod is connected.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connection statics:&lt;/strong&gt; Includes basic metrics from sockets, such as round-trip time (&lt;a href=&#34;https://en.wikipedia.org/wiki/Round-trip_delay&#34;&gt;RTT&lt;/a&gt;), lost packet count in TCP, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Socket and file descriptor (&lt;a href=&#34;https://en.wikipedia.org/wiki/File_descriptor&#34;&gt;FD&lt;/a&gt;) mapping:&lt;/strong&gt; Includes the relationship between the Linux file descriptor and socket object. It is useful when sending and receiving data through a Linux file descriptor.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;sendreceive&#34;&gt;Send/Receive&lt;/h4&gt;
&lt;p&gt;The interface related to sending or receiving data is the focus of
performance analysis. It mainly contains the following parameters:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Socket file descriptor:&lt;/strong&gt; The file descriptor of the current operation corresponding to the socket.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Buffer:&lt;/strong&gt; The data sent or received, passed as a byte array.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Based on the above parameters, we can analyze the following data:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Bytes:&lt;/strong&gt; The size of the packet in bytes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Protocol:&lt;/strong&gt; The protocol analysis according to the buffer data, such as HTTP, MySQL, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Execution Time:&lt;/strong&gt; The time it takes to send/receive the data.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At this point (Figure 1) we can analyze the following steps for the
whole lifecycle of the connection:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Connect/Accept:&lt;/strong&gt; When the connection is created.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transform:&lt;/strong&gt; Sending and receiving data on the connection.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Close:&lt;/strong&gt; When the connection is closed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;f1.svg&#34; alt=&#34;Figure 1&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 1&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;protocol-and-tls&#34;&gt;Protocol and TLS&lt;/h3&gt;
&lt;p&gt;The previous section described how to analyze connections using send or receive buffer data. For example, following the &lt;a href=&#34;https://www.rfc-editor.org/rfc/rfc2068.html#section-4.1&#34;&gt;HTTP/1.1 message specification&lt;/a&gt; to analyze the connection. However, this does not work for TLS requests/responses.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;f2.svg&#34; alt=&#34;Figure 2&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 2&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When TLS is in use, the Linux Kernel transmits data encrypted in user space. In the figure above, The application usually transmits SSL data through a third-party library (such as OpenSSL). For this case, the Linux API can only get the encrypted data, so it cannot recognize any higher layer protocol. To decrypt inside eBPF, we need to follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Read unencrypted data through uprobe:&lt;/strong&gt; Compatible multiple languages, using uprobe to capture the data that is not encrypted before sending or after receiving. In this way, we can get the original data and associate it with the socket.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Associate with socket:&lt;/strong&gt; We can associate unencrypted data with the socket.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&#34;openssl-use-case&#34;&gt;OpenSSL Use case&lt;/h4&gt;
&lt;p&gt;For example, the most common way to send/receive SSL data is to use OpenSSL as a shared library, specifically the &lt;a href=&#34;https://www.openssl.org/docs/man1.1.1/man3/SSL_read.html&#34;&gt;SSL_read&lt;/a&gt; and &lt;a href=&#34;https://www.openssl.org/docs/man1.1.1/man3/SSL_write.html&#34;&gt;SSL_write&lt;/a&gt; methods to submit the buffer data with the socket.&lt;/p&gt;
&lt;p&gt;Following the &lt;a href=&#34;https://www.openssl.org/docs/man1.1.1/man7/ssl.html&#34;&gt;documentation&lt;/a&gt;, we can intercept these two methods, which are almost identical to the API in Linux. The source code of the SSL structure in OpenSSL shows that the &lt;a href=&#34;https://github.com/openssl/openssl/blob/9eae491721209f302a9a475bffd271370e8bcb8f/crypto/bio/bio_local.h#L115-L125&#34;&gt;Socket FD&lt;/a&gt; exists in the &lt;a href=&#34;https://github.com/openssl/openssl/blob/9eae491721209f302a9a475bffd271370e8bcb8f/ssl/ssl_local.h#L1068-L1083&#34;&gt;BIO object of the SSL structure&lt;/a&gt;, and we can get it by the offset.&lt;/p&gt;
&lt;p&gt;In summary, with knowledge of how OpenSSL works, we can read unencrypted data in an eBPF function.&lt;/p&gt;
&lt;h2 id=&#34;introducing-skywalking-rover-an-ebpf-based-metrics-collector-and-profiler&#34;&gt;Introducing SkyWalking Rover, an eBPF-based Metrics Collector and Profiler&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/apache/skywalking-rover&#34;&gt;SkyWalking Rover&lt;/a&gt; introduces the eBPF network profiling feature into the SkyWalking ecosystem. It&amp;rsquo;s currently supported in a Kubernetes environment, so must be deployed inside a Kubernetes cluster. Once the deployment is complete, SkyWalking Rover can monitor the network for all processes inside a given Pod. Based on the monitoring data, SkyWalking can generate the topology relationship diagram and metrics between processes.&lt;/p&gt;
&lt;h3 id=&#34;topology-diagram&#34;&gt;Topology Diagram&lt;/h3&gt;
&lt;p&gt;The topology diagram can help us understand the network access between processes inside the same Pod, and between the process and external environment (other Pod or service). Additionally, it can identify the data direction of traffic based on the line flow direction.&lt;/p&gt;
&lt;p&gt;In Figure 3 below, all nodes within the hexagon are the internal process of a Pod, and nodes outside the hexagon are externally associated services or Pods. Nodes are connected by lines, which indicate the direction of requests or responses between nodes (client or server). The protocol is indicated on the line, and it&amp;rsquo;s either HTTP(S), TCP, or TCP(TLS). Also, we can see in this figure that the line between Envoy and Python applications is bidirectional because Envoy intercepts all application traffic.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;f3.jpg&#34; alt=&#34;Figure 3&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 3&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;metrics&#34;&gt;Metrics&lt;/h3&gt;
&lt;p&gt;Once we recognize the network call relationship between processes through the topology, we can select a specific line and view the TCP metrics between the two processes.&lt;/p&gt;
&lt;p&gt;The diagram below (Figure 4) shows the metrics of network monitoring between two processes. There are four metrics in each line. Two on the left side are on the client side, and two on the right side are on the server side. If the remote process is not in the same Pod, only one side of the metrics is displayed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;f4.jpg&#34; alt=&#34;Figure 4&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 4&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The following two metric types are available:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Counter:&lt;/strong&gt; Records the total number of data in a certain period. Each counter contains the following data:
a.  &lt;strong&gt;Count:&lt;/strong&gt; Execution count.
b.  &lt;strong&gt;Bytes:&lt;/strong&gt; Packet size in bytes.
c.  &lt;strong&gt;Execution time:&lt;/strong&gt; Execution duration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Histogram:&lt;/strong&gt; Records the distribution of data in the buckets.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Based on the above data types, the following metrics are exposed:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Name&lt;/th&gt;
          &lt;th&gt;Type&lt;/th&gt;
          &lt;th&gt;Unit&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Write&lt;/td&gt;
          &lt;td&gt;Counter and histogram&lt;/td&gt;
          &lt;td&gt;Millisecond&lt;/td&gt;
          &lt;td&gt;The socket write counter.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Read&lt;/td&gt;
          &lt;td&gt;Counter and histogram&lt;/td&gt;
          &lt;td&gt;Millisecond&lt;/td&gt;
          &lt;td&gt;The socket read counter.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Write RTT&lt;/td&gt;
          &lt;td&gt;Counter and histogram&lt;/td&gt;
          &lt;td&gt;Microsecond&lt;/td&gt;
          &lt;td&gt;The socket write round trip time (RTT) counter.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Connect&lt;/td&gt;
          &lt;td&gt;Counter and histogram&lt;/td&gt;
          &lt;td&gt;Millisecond&lt;/td&gt;
          &lt;td&gt;The socket connect/accept with another server/client counter.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Close&lt;/td&gt;
          &lt;td&gt;Counter and histogram&lt;/td&gt;
          &lt;td&gt;Millisecond&lt;/td&gt;
          &lt;td&gt;The socket with other socket counter.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Retransmit&lt;/td&gt;
          &lt;td&gt;Counter&lt;/td&gt;
          &lt;td&gt;Millisecond&lt;/td&gt;
          &lt;td&gt;The socket retransmit package counter.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Drop&lt;/td&gt;
          &lt;td&gt;Counter&lt;/td&gt;
          &lt;td&gt;Millisecond&lt;/td&gt;
          &lt;td&gt;The socket drop package counter.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;demo&#34;&gt;Demo&lt;/h2&gt;
&lt;p&gt;In this section, we demonstrate how to perform network profiling in the
service mesh. To follow along, you will need a running Kubernetes
environment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; All commands and scripts are available &lt;a href=&#34;https://github.com/mrproliu/skywalking-network-profiling-demo&#34;&gt;in this GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;install-istio&#34;&gt;Install Istio&lt;/h3&gt;
&lt;p&gt;Istio is the most widely deployed service mesh, and comes with a complete demo application that we can use for testing. To install Istio and the demo application, follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install Istio using the demo configuration profile.&lt;/li&gt;
&lt;li&gt;Label the default namespace, so Istio automatically injects Envoy sidecar proxies when we&amp;rsquo;ll deploy the application.&lt;/li&gt;
&lt;li&gt;Deploy the bookinfo application to the cluster.&lt;/li&gt;
&lt;li&gt;Deploy the traffic generator to generate some traffic to the application.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#953800&#34;&gt;ISTIO_VERSION&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;1.13.1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# install istio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;istioctl install -y --set &lt;span style=&#34;color:#953800&#34;&gt;profile&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;demo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl label namespace default istio-injection&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;enabled
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# deploy the bookinfo applications&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/istio/istio/&lt;span style=&#34;color:#953800&#34;&gt;$ISTIO_VERSION&lt;/span&gt;/samples/bookinfo/platform/kube/bookinfo.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/istio/istio/&lt;span style=&#34;color:#953800&#34;&gt;$ISTIO_VERSION&lt;/span&gt;/samples/bookinfo/networking/bookinfo-gateway.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/istio/istio/&lt;span style=&#34;color:#953800&#34;&gt;$ISTIO_VERSION&lt;/span&gt;/samples/bookinfo/networking/destination-rule-all.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/istio/istio/&lt;span style=&#34;color:#953800&#34;&gt;$ISTIO_VERSION&lt;/span&gt;/samples/bookinfo/networking/virtual-service-all-v1.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# generate traffic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/mrproliu/skywalking-network-profiling-demo/main/resources/traffic-generator.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;install-skywalking&#34;&gt;Install SkyWalking&lt;/h3&gt;
&lt;p&gt;The following will install the storage, backend, and UI needed for SkyWalking:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone https://github.com/apache/skywalking-kubernetes.git
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;cd&lt;/span&gt; skywalking-kubernetes
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;cd&lt;/span&gt; chart
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;helm dep up skywalking
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;helm -n istio-system install skywalking skywalking &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set &lt;span style=&#34;color:#953800&#34;&gt;fullnameOverride&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;skywalking &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set elasticsearch.minimumMasterNodes&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set elasticsearch.imageTag&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;7.5.1 &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set oap.replicas&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set ui.image.repository&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;apache/skywalking-ui &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set ui.image.tag&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;9.2.0 &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set oap.image.tag&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;9.2.0 &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set oap.envoy.als.enabled&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set oap.image.repository&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;apache/skywalking-oap-server &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set oap.storageType&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;elasticsearch &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --set oap.env.SW_METER_ANALYZER_ACTIVE_FILES&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#0a3069&#34;&gt;&amp;#39;network-profiling&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;install-skywalking-rover&#34;&gt;Install SkyWalking Rover&lt;/h3&gt;
&lt;p&gt;SkyWalking Rover is deployed on every node in Kubernetes, and it automatically detects the services in the Kubernetes cluster. The network profiling feature has been released in the version 0.3.0 of SkyWalking Rover. When a network monitoring task is created, the SkyWalking rover sends the data to the SkyWalking backend.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/mrproliu/skywalking-network-profiling-demo/main/resources/skywalking-rover.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;start-the-network-profiling-task&#34;&gt;Start the Network Profiling Task&lt;/h3&gt;
&lt;p&gt;Once all deployments are completed, we must create a network profiling task for a specific instance of the service in the SkyWalking UI.&lt;/p&gt;
&lt;p&gt;To open SkyWalking UI, run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl port-forward svc/skywalking-ui 8080:80 --namespace
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;istio-system
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Currently, we can select the specific instances that we wish to monitor by clicking the &lt;strong&gt;Data Plane&lt;/strong&gt; item in the Service Mesh panel and the &lt;strong&gt;Service&lt;/strong&gt; item in the &lt;strong&gt;Kubernetes&lt;/strong&gt; panel.&lt;/p&gt;
&lt;p&gt;In the figure below, we have selected an instance with a list of tasks in the network profiling tab. When we click the start button, the SkyWalking Rover starts monitoring this instance&amp;rsquo;s network.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;f5.jpg&#34; alt=&#34;Figure 5&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 5&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;done&#34;&gt;Done!&lt;/h3&gt;
&lt;p&gt;After a few seconds, you will see the process topology appear on the right side of the page.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;f6.jpg&#34; alt=&#34;Figure 6&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 6&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When you click on the line between processes, you can see the TCP metrics between the two processes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;f7.jpg&#34; alt=&#34;Figure 7&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 7&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this article, we detailed a problem that makes troubleshooting service mesh architectures difficult: lack of context between layers in the network stack. These are the cases when eBPF begins to really help with debugging/productivity when existing service mesh/envoy cannot. Then, we researched how eBPF could be applied to common communication, such as TLS. Finally, we demo the implementation of this process with SkyWalking Rover.&lt;/p&gt;
&lt;p&gt;For now, we have completed the performance analysis for OSI layer 4 (mostly TCP). In the future, we will also introduce the analysis for OSI layer 7 protocols like HTTP.&lt;/p&gt;
&lt;h2 id=&#34;get-started-with-istio&#34;&gt;Get Started with Istio&lt;/h2&gt;
&lt;p&gt;To &lt;a href=&#34;https://istio.tetratelabs.io/&#34;&gt;get started with service mesh today, Tetrate Istio Distro&lt;/a&gt; is the easiest way to install, manage, and upgrade Istio. It provides a vetted upstream distribution of Istio that&amp;rsquo;s tested and optimized for specific platforms by Tetrate plus a CLI that facilitates acquiring, installing, and configuring multiple Istio versions. Tetrate Istio Distro also offers &lt;a href=&#34;https://www.tetrate.io/blog/tetrate-istio-distro-achieves-fips-certification/&#34;&gt;FIPS certified Istio builds&lt;/a&gt; for FedRAMP environments.&lt;/p&gt;
&lt;p&gt;For enterprises that need a unified and consistent way to secure and manage services and traditional workloads across complex, heterogeneous deployment environments, we offer &lt;a href=&#34;https://www.tetrate.io/tetrate-service-bridge/&#34;&gt;Tetrate Service Bridge&lt;/a&gt;, our flagship edge-to-workload application connectivity platform built on Istio and Envoy.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.tetrate.io/contact/&#34;&gt;Contact us to learn more&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;additional-resources&#34;&gt;Additional Resources&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apache/skywalking&#34;&gt;SkyWalking Github Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/apache/skywalking-rover&#34;&gt;SkyWalking Rover Github Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://skywalking.apache.org/docs/skywalking-rover/v0.3.0/readme/&#34;&gt;SkyWalking Rover Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://skywalking.apache.org/blog/2022-07-05-pinpoint-service-mesh-critical-performance-impact-by-using-ebpf/&#34;&gt;Pinpoint Service Mesh Critical Performance impact by using eBPF blog post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=yUF5qRk4rYY&#34;&gt;Apache SkyWalking with Native eBPF Agent presentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ebpf.io/what-is-ebpf#hook-overview&#34;&gt;eBPF hook overview&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

      </description>
    </item>
    
    <item>
      <title>Blog: Scaling with Apache SkyWalking</title>
      <link>/blog/2022-01-24-scaling-with-apache-skywalking/</link>
      <pubDate>Mon, 24 Jan 2022 00:00:00 +0000</pubDate>
      <guid>/blog/2022-01-24-scaling-with-apache-skywalking/</guid>
      <description>
        
        
        &lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;In the Apache SkyWalking ecosystem, the OAP obtains metrics, traces, logs, and event data through SkyWalking Agent, Envoy, or other data sources. Under the gRPC protocol, it transmits data by communicating with a single server node. Only when the connection is broken, the reconnecting policy would be used based on DNS round-robin mode. When new services are added at runtime or the OAP load is kept high due to increased traffic of observed services, the OAP cluster needs to scale out for increased traffic. The load of the new OAP node would be less due to all existing agents having connected to previous nodes. Even without scaling, the load of OAP nodes would be unbalanced, because the agent would keep the connection due to random policy at the booting stage. In these cases, it would become a challenge to keep up the health status of all nodes, and be able to scale out when needed.&lt;/p&gt;
&lt;p&gt;In this article, we mainly discuss how to solve this challenge in SkyWalking.&lt;/p&gt;
&lt;h2 id=&#34;how-to-load-balance&#34;&gt;How to Load Balance&lt;/h2&gt;
&lt;p&gt;SkyWalking mainly uses the gRPC protocol for data transmission, so this article mainly introduces load balancing in the gRPC protocol.&lt;/p&gt;
&lt;h3 id=&#34;proxy-or-client-side&#34;&gt;Proxy Or Client-side&lt;/h3&gt;
&lt;p&gt;Based on the &lt;a href=&#34;https://grpc.io/blog/grpc-load-balancing/&#34;&gt;gRPC official Load Balancing blog&lt;/a&gt;, there are two approaches to load balancing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Client-side&lt;/strong&gt;: The client perceives multiple back-end services and uses a load-balancing algorithm to select a back-end service for each RPC.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proxy&lt;/strong&gt;: The client sends the message to the proxy server, and the proxy server load balances the message to the back-end service.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From the perspective of observability system architecture:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;/th&gt;
          &lt;th&gt;Pros&lt;/th&gt;
          &lt;th&gt;Cons&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Client-side&lt;/td&gt;
          &lt;td&gt;&lt;li&gt;High performance because of the elimination of extra hop&lt;/li&gt;&lt;/td&gt;
          &lt;td&gt;&lt;li&gt;Complex client (cluster awareness, load balancing, health check, etc.)&lt;/li&gt;&lt;li&gt;Ensure each data source to be connected provides complex client capabilities&lt;/li&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Proxy&lt;/td&gt;
          &lt;td&gt;&lt;li&gt;Simple Client&lt;/li&gt;&lt;/td&gt;
          &lt;td&gt;&lt;li&gt;Higher latency&lt;/li&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We choose Proxy mode for the following reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Observable data is not very time-sensitive, a little latency caused by transmission is acceptable. A little extra hop is acceptable and there is no impact on the client-side.&lt;/li&gt;
&lt;li&gt;As an observability platform, we cannot/should not ask clients to change. They make their own tech decisions and may have their own commercial considerations.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;transmission-policy&#34;&gt;Transmission Policy&lt;/h3&gt;
&lt;p&gt;In the proxy mode, we should determine the transmission path between downstream and upstream.&lt;/p&gt;
&lt;p&gt;Different data protocols require different processing policies. There are two transmission policies:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Synchronous&lt;/strong&gt;: Suitable for protocols that require data exchange in the client, such as SkyWalking Dynamic Configuration Service. This type of protocol provides real-time results.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Asynchronous batch&lt;/strong&gt;: Used when the client doesn’t care about the upstream processing results, but only the transmitted data (e.g., trace report, log report, etc.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The synchronization policy requires that the proxy send the message to the upstream server when receiving the client message, and synchronously return the response data to the downstream client. Usually, only a few protocols need to use the synchronization policy.&lt;/p&gt;
&lt;p&gt;As shown below, after the client sends the request to the Proxy, the proxy would send the message to the server synchronously. When the proxy receives the result, it returns to the client.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./transmission-policy-synchronous.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The asynchronous batch policy means that the data is sent to the upstream server in batches asynchronously. This policy is more common because most protocols in SkyWalking are primarily based on data reporting. We think using the queue as a buffer could have a good effect. The asynchronous batch policy is executed according to the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The proxy receives the data and wraps it as an Event object.&lt;/li&gt;
&lt;li&gt;An event is added into the queue.&lt;/li&gt;
&lt;li&gt;When the cycle time is reached or when the queue elements reach the fixed number, the elements in the queue will parallel consume and send to the OAP.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The advantage of using queues is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Separate data receiving and sending to reduce the mutual influence.&lt;/li&gt;
&lt;li&gt;The interval quantization mechanism can be used to combine events, which helps to speed up sending events to the OAP.&lt;/li&gt;
&lt;li&gt;Using multi-threaded consumption queue events can make fuller use of network IO.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As shown below, after the proxy receives the message, the proxy would wrap the message as an event and push it to the queue. The message sender would take batch events from the queue and send them to the upstream OAP.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./transmission-policy-asynchronous.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;routing&#34;&gt;Routing&lt;/h3&gt;
&lt;p&gt;Routing algorithms are used to route messages to a single upstream server node.&lt;/p&gt;
&lt;p&gt;The Round-Robin algorithm selects nodes in order from the list of upstream service nodes. The advantage of this algorithm is that the number of times each node is selected is average. When the size of the data is close to the same, each upstream node can handle the same quantity of data content.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./routing-round-robin.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;With the Weight Round-Robin, each upstream server node has a corresponding routing weight ratio. The difference from Round-Robin is that each upstream node has more chances to be routed according to its weight. This algorithm is more suitable to use when the upstream server node machine configuration is not the same.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./routing-weight-round-robin.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The Fixed algorithm is a hybrid algorithm. It can ensure that the same data is routed to the same upstream server node, and when the upstream server scales out, it still maintains routing to the same node; unless the upstream node does not exist, it will reroute. This algorithm is mainly used in the SkyWalking Meter protocol because this protocol needs to ensure that the metrics of the same service instance are sent to the same OAP node.
The Routing steps are as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generate a unique identification string based on the data content, as short as possible. The amount of data is controllable.&lt;/li&gt;
&lt;li&gt;Get the upstream node of identity from LRU Cache, and use it if it exists.&lt;/li&gt;
&lt;li&gt;According to the identification, generate the corresponding hash value, and find the upstream server node from the upstream list.&lt;/li&gt;
&lt;li&gt;Save the mapping relationship between the upstream server node and identification to LRU Cache.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The advantage of this algorithm is to bind the data with the upstream server node as much as possible, so the upstream server can better process continuous data. The disadvantage is that it takes up a certain amount of memory space to save the corresponding relationship.&lt;/p&gt;
&lt;p&gt;As shown below, the image is divided into two parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The left side represents that the same data content always is routed to the same server node.&lt;/li&gt;
&lt;li&gt;The right side represents the data routing algorithm. Get the number from the data, and use the remainder algorithm to obtain the position.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;./routing-fixed.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;We choose to use a combination of Round-Robin and Fixed algorithm for routing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The Fixed routing algorithm is suitable for specific protocols, mainly used when passing metrics data to the SkyWalking Meter protocol&lt;/li&gt;
&lt;li&gt;The Round-Robin algorithm is used by default. When the SkyWalking OAP cluster is deployed, the configuration of the nodes needs to be as much the same as possible, so there would be no need to use the Weight Round-Robin algorithm.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;how-to-balance-the-load-balancer-itself&#34;&gt;How to balance the load balancer itself?&lt;/h2&gt;
&lt;p&gt;Proxy still needs to deal with the load balancing problem from client to itself, especially when deploying a Proxy cluster in a production environment.&lt;/p&gt;
&lt;p&gt;There are three ways to solve this problem:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Connection management&lt;/strong&gt;: Use the &lt;code&gt;max_connection&lt;/code&gt; config on the client-side to specify the maximum connection duration of each connection. For more information, please read the &lt;a href=&#34;https://github.com/grpc/proposal/blob/master/A9-server-side-conn-mgt.md&#34;&gt;proposal&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cluster awareness&lt;/strong&gt;: The proxy has cluster awareness, and actively disconnects the connection when the load is unbalanced to allow the client to re-pick up the proxy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resource limit+HPA&lt;/strong&gt;: Restrict the connection resource situation of each proxy, and no longer accept new connections when the resource limit is reached. And use the HPA mechanism of Kubernetes to dynamically scale out the number of the proxy.&lt;/li&gt;
&lt;/ol&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;/th&gt;
          &lt;th&gt;Connection management&lt;/th&gt;
          &lt;th&gt;Cluster awareness&lt;/th&gt;
          &lt;th&gt;Resource Limit+HPA&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Pros&lt;/td&gt;
          &lt;td&gt;&lt;li&gt;Simple to use&lt;/li&gt;&lt;/td&gt;
          &lt;td&gt;&lt;li&gt;Ensure that the number of connections in each proxy is relatively &lt;/li&gt;&lt;/td&gt;
          &lt;td&gt;&lt;li&gt;Simple to use&lt;/li&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Cons&lt;/td&gt;
          &lt;td&gt;&lt;li&gt;Each client needs to ensure that data is not lost&lt;/li&gt;&lt;li&gt;The client is required to accept GOWAY responses&lt;/li&gt;&lt;/td&gt;
          &lt;td&gt;&lt;li&gt;May cause a sudden increase in traffic on some nodes&lt;/li&gt;&lt;li&gt;Each client needs to ensure that data is not lost &lt;/li&gt;&lt;/td&gt;
          &lt;td&gt;&lt;li&gt;Traffic will not be particularly balanced in each instance&lt;/li&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We choose Limit+HPA for these reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Easy to config and use the proxy and easy to understand based on basic data metrics.&lt;/li&gt;
&lt;li&gt;No data loss due to broken connection. There is no need for the client to implement any other protocols to prevent data loss, especially when the client is a commercial product.&lt;/li&gt;
&lt;li&gt;The connection of each node in the proxy cluster does not need to be particularly balanced, as long as the proxy node itself is high-performance.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;skywalking-satellite&#34;&gt;SkyWalking-Satellite&lt;/h2&gt;
&lt;p&gt;We have implemented this Proxy in the &lt;a href=&#34;https://github.com/apache/skywalking-satellite&#34;&gt;SkyWalking-Satellite&lt;/a&gt; project. It’s used between Client and SkyWalking OAP, effectively solving the load balancing problem.&lt;/p&gt;
&lt;p&gt;After the system is deployed, the Satellite would accept the traffic from the Client, and the Satellite will perceive all the nodes of the OAP through Kubernetes Label Selector or manual configuration, and load balance the traffic to the upstream OAP node.&lt;/p&gt;
&lt;p&gt;As shown below, a single client still maintains a connection with a single Satellite, Satellite would establish the connection with each OAP, and load balance message to the OAP node.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./skywalking-satellites.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;When scaling Satellite, we need to deploy the &lt;a href=&#34;https://github.com/apache/skywalking-swck&#34;&gt;SWCK&lt;/a&gt; adapter and configure the HPA in Kubernetes. SWCK is a platform for the SkyWalking users, provisions, upgrades, maintains SkyWalking relevant components, and makes them work natively on Kubernetes.&lt;/p&gt;
&lt;p&gt;After deployment is finished, the following steps would be performed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Read metrics from OAP&lt;/strong&gt;: HPA requests the SWCK metrics adapter to dynamically read the metrics in the OAP.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scaling the Satellite&lt;/strong&gt;: Kubernetes HPA senses that the metrics values are in line with expectations, so the Satellite would be scaling automatically.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As shown below, use the dotted line to divide the two parts. HPA uses SWCK Adapter to read the metrics in the OAP. When the threshold is met, HPA would scale the Satellite deployment.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;swck-hpa.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;
&lt;p&gt;In this section, we will demonstrate two cases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SkyWalking Scaling: After SkyWalking OAP scaling, the traffic would auto load balancing through Satellite.&lt;/li&gt;
&lt;li&gt;Satellite Scaling: Satellite’s own traffic load balancing.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;NOTE: All commands could be accessed through &lt;a href=&#34;https://github.com/mrproliu/sw-satellite-demo-scripts/tree/1180c23e8f3bb36778307f9ae15395274ca039b3&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;skywalking-scaling&#34;&gt;SkyWalking Scaling&lt;/h3&gt;
&lt;p&gt;We will use the &lt;a href=&#34;https://istio.io/latest/docs/examples/bookinfo/&#34;&gt;bookinfo application&lt;/a&gt; to demonstrate how to integrate Apache SkyWalking 8.9.1 with Apache SkyWalking-Satellite 0.5.0, and observe the service mesh through the Envoy ALS protocol.&lt;/p&gt;
&lt;p&gt;Before starting, please make sure that you already have a Kubernetes environment.&lt;/p&gt;
&lt;h4 id=&#34;install-istio&#34;&gt;Install Istio&lt;/h4&gt;
&lt;p&gt;Istio provides a very convenient way to configure the Envoy proxy and enable the access log service. The following step:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install the istioctl locally to help manage the Istio mesh.&lt;/li&gt;
&lt;li&gt;Install Istio into the Kubernetes environment with a demo configuration profile, and enable the Envoy ALS. Transmit the ALS message to the satellite. The satellite we will deploy later.&lt;/li&gt;
&lt;li&gt;Add the label into the default namespace so Istio could automatically inject Envoy sidecar proxies when you deploy your application later.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# install istioctl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#953800&#34;&gt;ISTIO_VERSION&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;1.12.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -L https://istio.io/downloadIstio &lt;span style=&#34;color:#1f2328&#34;&gt;|&lt;/span&gt; sh - 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo mv &lt;span style=&#34;color:#953800&#34;&gt;$PWD&lt;/span&gt;/istio-&lt;span style=&#34;color:#953800&#34;&gt;$ISTIO_VERSION&lt;/span&gt;/bin/istioctl /usr/local/bin/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# install istio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;istioctl install -y --set &lt;span style=&#34;color:#953800&#34;&gt;profile&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;demo &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	--set meshConfig.enableEnvoyAccessLogService&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#0a3069&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	--set meshConfig.defaultConfig.envoyAccessLogService.address&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;skywalking-system-satellite.skywalking-system:11800
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# enbale envoy proxy in default namespace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl label namespace default istio-injection&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;enabled
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;install-swck&#34;&gt;Install SWCK&lt;/h4&gt;
&lt;p&gt;SWCK provides convenience for users to deploy and upgrade SkyWalking related components based on Kubernetes. The automatic scale function of Satellite also mainly relies on SWCK. For more information, you could refer to the &lt;a href=&#34;https://github.com/apache/skywalking-swck/blob/master/docs/operator.md#guides-of-operator-deployment&#34;&gt;official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# Install cert-manager&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# Deploy SWCK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mkdir -p skywalking-swck &lt;span style=&#34;color:#0550ae&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#6639ba&#34;&gt;cd&lt;/span&gt; skywalking-swck
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;wget https://dlcdn.apache.org/skywalking/swck/0.6.1/skywalking-swck-0.6.1-bin.tgz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tar -zxvf skywalking-swck-0.6.1-bin.tgz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;cd&lt;/span&gt; config
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f operator-bundle.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;deploy-apache-skywalking-and-apache-skywalking-satellite&#34;&gt;Deploy Apache SkyWalking And Apache SkyWalking-Satellite&lt;/h4&gt;
&lt;p&gt;We have provided a simple script to deploy the skywalking OAP, UI, and Satellite.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# Create the skywalking components namespace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl create namespace skywalking-system
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl label namespace skywalking-system swck-injection&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;enabled
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# Deploy components&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/mrproliu/sw-satellite-demo-scripts/5821a909b647f7c8f99c70378e197630836f45f7/resources/sw-components.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;deploy-bookinfo-application&#34;&gt;Deploy Bookinfo Application&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6639ba&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#953800&#34;&gt;ISTIO_VERSION&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;1.12.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/istio/istio/&lt;span style=&#34;color:#953800&#34;&gt;$ISTIO_VERSION&lt;/span&gt;/samples/bookinfo/platform/kube/bookinfo.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl &lt;span style=&#34;color:#6639ba&#34;&gt;wait&lt;/span&gt; --for&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#953800&#34;&gt;condition&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;Ready pods --all --timeout&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;1200s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl port-forward service/productpage &lt;span style=&#34;color:#0550ae&#34;&gt;9080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, please open your browser and visit &lt;code&gt;http://localhost:9080&lt;/code&gt;. You should be able to see the Bookinfo application. Refresh the webpage several times to generate enough access logs.&lt;/p&gt;
&lt;p&gt;Then, you can see the topology and metrics of the Bookinfo application on SkyWalking WebUI. At this time, you can see that the Satellite is working!&lt;/p&gt;
&lt;h4 id=&#34;deploy-monitor&#34;&gt;Deploy Monitor&lt;/h4&gt;
&lt;p&gt;We need to install OpenTelemetry Collector to collect metrics in OAPs and analyze them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#57606a&#34;&gt;# Add OTEL collector&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/mrproliu/sw-satellite-demo-scripts/5821a909b647f7c8f99c70378e197630836f45f7/resources/otel-collector-oap.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl port-forward -n skywalking-system  service/skywalking-system-ui 8080:80
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, please open your browser and visit &lt;code&gt;http://localhost:8080/&lt;/code&gt; and create a new item on the dashboard. The SkyWalking Web UI pictured below shows how the data content is applied.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./mesh-count-conf.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h4 id=&#34;scaling-oap&#34;&gt;Scaling OAP&lt;/h4&gt;
&lt;p&gt;Scaling the number of OAPs by deployment.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl scale --replicas&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;3&lt;/span&gt; -n skywalking-system deployment/skywalking-system-oap
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;done&#34;&gt;Done!&lt;/h4&gt;
&lt;p&gt;After a period of time, you will see that the number of OAPs becomes 3, and the ALS traffic is balanced to each OAP.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./mesh-count-list.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;satellite-scaling&#34;&gt;Satellite Scaling&lt;/h3&gt;
&lt;p&gt;After we have completed the SkyWalking Scaling, we would carry out the Satellite Scaling demo.&lt;/p&gt;
&lt;h4 id=&#34;deploy-swck-hpa&#34;&gt;Deploy SWCK HPA&lt;/h4&gt;
&lt;p&gt;SWCK provides an adapter to implement the Kubernetes external metrics to adapt the HPA through reading the metrics in SkyWalking OAP. We expose the metrics service in Satellite to OAP and configure HPA Resource to auto-scaling the Satellite.&lt;/p&gt;
&lt;p&gt;Install the SWCK adapter into the Kubernetes environment:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f skywalking-swck/config/adapter-bundle.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Create the HPA resource, and limit each Satellite to handle a maximum of 10 connections:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl apply -f https://raw.githubusercontent.com/mrproliu/sw-satellite-demo-scripts/5821a909b647f7c8f99c70378e197630836f45f7/resources/satellite-hpa.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, you could see we have 9 connections in one satellite. One envoy proxy may establish multiple connections to the satellite.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ kubectl get HorizontalPodAutoscaler -n skywalking-system
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NAME       REFERENCE                                TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hpa-demo   Deployment/skywalking-system-satellite   9/10      &lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;3&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt;          5m18s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;scaling-application&#34;&gt;Scaling Application&lt;/h4&gt;
&lt;p&gt;The scaling application could establish more connections to the satellite, to verify whether the HPA is in effect.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl scale --replicas&lt;span style=&#34;color:#0550ae&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#0550ae&#34;&gt;3&lt;/span&gt; deployment/productpage-v1 deployment/details-v1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;done-1&#34;&gt;Done!&lt;/h4&gt;
&lt;p&gt;By default, Satellite will deploy a single instance and a single instance will only accept 11 connections. HPA resources limit one Satellite to handle 10 connections and use a stabilization window to make Satellite stable scaling up. In this case, we deploy the Bookinfo application in 10+ instances after scaling, which means that 10+ connections will be established to the Satellite.&lt;/p&gt;
&lt;p&gt;So after HPA resources are running, the Satellite would be automatically scaled up to 2 instances. You can learn about the calculation algorithm of replicas through the &lt;a href=&#34;https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#algorithm-details&#34;&gt;official documentation&lt;/a&gt;. Run the following command to view the running status:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ kubectl get HorizontalPodAutoscaler -n skywalking-system --watch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NAME       REFERENCE                                TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hpa-demo   Deployment/skywalking-system-satellite   11/10     &lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;3&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt;          3m31s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hpa-demo   Deployment/skywalking-system-satellite   11/10     &lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;3&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt;          4m20s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hpa-demo   Deployment/skywalking-system-satellite   11/10     &lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;3&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;2&lt;/span&gt;          4m38s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hpa-demo   Deployment/skywalking-system-satellite   11/10     &lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;3&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;2&lt;/span&gt;          5m8s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hpa-demo   Deployment/skywalking-system-satellite   6/10      &lt;span style=&#34;color:#0550ae&#34;&gt;1&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;3&lt;/span&gt;         &lt;span style=&#34;color:#0550ae&#34;&gt;2&lt;/span&gt;          5m23s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By observing the “number of connections” metric, we would be able to see that when the number of connections of each gRPC exceeds 10 connections, then the satellite automatically scales through the HPA rule. As a result, the connection number is down to normal status (in this example, less than 10)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swctl metrics linear --name satellite_service_grpc_connect_count --service-name satellite::satellite-service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;satellite-connection-metrics.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Blog: SkyWalking performance in Service Mesh scenario</title>
      <link>/blog/2019-01-25-mesh-loadtest/</link>
      <pubDate>Fri, 25 Jan 2019 00:00:00 +0000</pubDate>
      <guid>/blog/2019-01-25-mesh-loadtest/</guid>
      <description>
        
        
        &lt;ul&gt;
&lt;li&gt;Author: Hongtao Gao, Apache SkyWalking &amp;amp; ShardingShpere PMC&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hanahmily&#34;&gt;GitHub&lt;/a&gt;, &lt;a href=&#34;https://twitter.com/hanahmily&#34;&gt;Twitter&lt;/a&gt;, &lt;a href=&#34;https://www.linkedin.com/in/gao-hongtao-47b835168/&#34;&gt;Linkedin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Service mesh receiver was first introduced in Apache SkyWalking 6.0.0-beta. It is designed to provide a common entrance for receiving telemetry data from service mesh framework, for instance, Istio, Linkerd, Envoy etc. What’s the service mesh? According to Istio’s explain:&lt;/p&gt;
&lt;p&gt;The term service mesh is used to describe the network of microservices that make up such applications and the interactions between them.&lt;/p&gt;
&lt;p&gt;As a PMC member of Apache SkyWalking, I tested trace receiver and well understood the performance of collectors in trace scenario. I also would like to figure out the performance of service mesh receiver.&lt;/p&gt;
&lt;h2 id=&#34;different-between-trace-and-service-mesh&#34;&gt;Different between trace and service mesh&lt;/h2&gt;
&lt;p&gt;Following chart presents a typical trace map:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;image5.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;You could find a variety of elements in it just like web service, local method, database, cache, MQ and so on. But service mesh only collect service network telemetry data that contains the entrance and exit data of a service for now(more elements will be imported soon, just like Database). A smaller quantity of data is sent to the service mesh receiver than the trace.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;image1.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;But using sidecar is a little different.The client requesting “A” that will send a segment to service mesh receiver from “A”’s sidecar. If “A” depends on “B”,  another segment will be sent from “A”’s sidecar. But for a trace system, only one segment is received by the collector. The sidecar model splits one segment into small segments, that will increase service mesh receiver network overhead.&lt;/p&gt;
&lt;h2 id=&#34;deployment-architecture&#34;&gt;Deployment Architecture&lt;/h2&gt;
&lt;p&gt;In this test, I will pick two different backend deployment. One is called mini unit, consist of one collector and one elasticsearch instance. Another is a standard production cluster, contains three collectors and three elasticsearch instances.&lt;/p&gt;
&lt;p&gt;Mini unit is a suitable architecture for dev or test environment. It saves your time and VM resources, speeds up depolyment process.&lt;/p&gt;
&lt;p&gt;The standard cluster provides good performance and HA for a production scenario. Though you will pay more money and take care of the cluster carefully, the reliability of the cluster will be a good reward to you.&lt;/p&gt;
&lt;p&gt;I pick 8 CPU and 16GB VM to set up the test environment. This test targets the performance of normal usage scenarios, so that choice is reasonable. The cluster is built on Google Kubernetes Engine(GKE), and every node links each other with a VPC network. For running collector is a CPU intensive task, the resource request of collector deployment should be 8 CPU, which means every collector instance occupy a VM node.&lt;/p&gt;
&lt;h2 id=&#34;testing-process&#34;&gt;Testing Process&lt;/h2&gt;
&lt;p&gt;Receiving mesh fragments per second(MPS) depends on the following variables.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ingress query per second(QPS)&lt;/li&gt;
&lt;li&gt;The topology of a microservice cluster&lt;/li&gt;
&lt;li&gt;Service mesh mode(proxy or sidecar)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this test, I use Bookinfo app as a demo cluster.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;image6.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;So every request will touch max 4 nodes. Plus picking the sidecar mode(every request will send two telemetry data),  the MPS will be QPS * 4 *2.&lt;/p&gt;
&lt;p&gt;There are also some important metrics that should be explained&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Client Query Latency: GraphQL API query response time heatmap.&lt;/li&gt;
&lt;li&gt;Client Mesh Sender: Send mesh segments per second. The total line represents total send amount and the error line is the total number of failed send.&lt;/li&gt;
&lt;li&gt;Mesh telemetry latency: service mesh receiver handling data heatmap.&lt;/li&gt;
&lt;li&gt;Mesh telemetry received: received mesh telemetry data per second.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;mini-unit&#34;&gt;Mini Unit&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;image3.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;You could find collector can process up to &lt;strong&gt;25k&lt;/strong&gt; data per second. The CPU usage is about 4 cores. Most of the query latency is less than 50ms. After login the VM on which collector instance running, I know that system load is reaching the limit(max is 8).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;image2.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;According to the previous formula, a single collector instance could process &lt;strong&gt;3k&lt;/strong&gt; QPS of Bookinfo traffic.&lt;/p&gt;
&lt;h3 id=&#34;standard-cluster&#34;&gt;Standard Cluster&lt;/h3&gt;
&lt;p&gt;&lt;img src=&#34;image4.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Compare to the mini-unit, cluster’s throughput increases linearly. Three instances provide total 80k per second processing power. Query latency increases slightly, but it’s also very small(less than 500ms). I also checked every collector instance system load that all reached the limit. 10k QPS of BookInfo telemetry data could be processed by the cluster.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Let’s wrap them up. There are some important things you could get from this test.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;QPS varies by the there variables. The test results in this blog are not important. The user should pick property value according to his system.&lt;/li&gt;
&lt;li&gt;Collector cluster’s processing power could scale out.&lt;/li&gt;
&lt;li&gt;The collector is CPU intensive application. So you should provide sufficient CPU resource to it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This blog gives people a common method to evaluate the throughput of Service Mesh Receiver. Users could use this to design their Apache Skywalking backend deployment architecture.&lt;/p&gt;

      </description>
    </item>
    
  </channel>
</rss>
