【Skywalking从入门到精通】第04篇:SkyWalking的三大设计哲学——面向协议、模块化、轻量化
上一篇【第03篇】SkyWalking架构全景图——四大组件的前世今生下一篇【第05篇】SkyWalking凭啥比Pinpoint快——性能优势的深层原因摘要很多人用SkyWalking只停留在会配置、会看图的层面而不理解它为什么这样设计。理解设计哲学有什么用至少有两个一是在二次开发时知道该往哪里加代码二是在系统出问题时能从设计层面理解根因而不是乱猜。SkyWalking的三大设计原则——面向协议、模块化、轻量化——听起来像PPT里的漂亮词汇但每一条背后都有真实的工程决策和血泪教训。一、设计哲学的重要性为什么要了解为什么有个经典的栏杆问题如果你看到一道栏杆你会不会直接拆掉它理智的回答是先搞清楚它为什么存在再决定要不要拆。设计哲学就是架构的栏杆说明书。当你理解了每个设计选择背后的原因你才能在扩展时顺势而为而不是对抗架构在遇到限制时理解是设计边界而不是Bug在与团队讨论时说出为什么而不只是怎么做二、第一哲学面向协议设计什么叫面向协议面向协议设计的核心思想是先定义好协议接口再实现功能。具体到SkyWalking它有两大类协议1. 探针协议Agent Protocol这是探针与OAP Server之间通信的协议分为四个子类语言探针上报协议Data Collect Protocol探针注册服务Trace数据上报Metrics数据上报命令下行Server→Agent的指令全部基于gRPC实现语言探针交互协议Propagation Protocol跨进程传播时使用的Header格式HTTP调用时注入HTTP HeaderMQ调用时注入Message Header当前执行的是v3协议从SkyWalking 8开始Service Mesh协议专为Service Mesh抽象的协议Istio/Envoy通过此协议上报Telemetry数据第三方协议兼容Zipkin格式数据兼容Jaeger格式数据部分版本2. 查询协议Query Protocol查询协议使用GraphQL格式定义分为6类┌──────────────────────────────────────────────────────────┐ │ SkyWalking GraphQL查询协议分类 │ ├──────────────┬────────────────────────────────────────┤ │ 协议类型 │ 查询能力 │ ├──────────────┼────────────────────────────────────────┤ │ 元数据查询 │ 查询服务/实例/Endpoint注册信息 │ │ 拓扑关系查询 │ 查询全局或单服务的依赖拓扑图 │ │ 线性指标查询 │ 查询时间序列指标折线图数据 │ │ 聚合指标查询 │ 区间均值、TopN查询 │ │ Trace查询 │ 查询具体的调用链路明细 │ │ 告警查询 │ 查询历史告警记录 │ └──────────────┴────────────────────────────────────────┘为什么面向协议设计好处1多语言生态探针协议一旦确定任何语言只要实现这套协议就能接入SkyWalking。这就是为什么SkyWalking能支持Java/.NET/Go/Node.js/PHP——它们共用同一套上报协议。Java探针 ─┐ .NET探针 ──┼──→ gRPC上报协议 ──→ OAP Server Go探针 ─┘ 协议是合同实现者各自负责好处2UI与后端解耦GraphQL查询协议让UI与OAP完全解耦。SkyWalking从5.x的原始UI切换到6.x的RocketBot UI时后端代码完全没有改动只是换了一个新的前端实现。这在传统RESTful架构下几乎不可能做到如此干净。好处3第三方集成任何系统只要能发送GraphQL请求就能从SkyWalking查询数据。很多公司基于此协议将SkyWalking数据集成进自己的运维平台。为什么用gRPC不用HTTP这是个常见问题。gRPC相对于HTTP JSON的优势性能Protocol Buffers序列化效率远高于JSON数据量更小强类型proto文件明确定义数据结构减少沟通成本流式传输支持Server-side streaming适合持续上报场景代码生成各语言自动生成客户端代码探针开发更简单三、第二哲学模块化设计什么叫模块化SkyWalking的模块化设计是整个OAP架构的骨架它的核心设计模式是Module ProviderModuleDefine模块定义声明一个功能模块有哪些服务接口类似Java的InterfaceModuleProvider模块实现实现某个模块的具体逻辑类似Java的实现类ModuleManager模块管理器在启动时根据配置文件选择并组装各模块的实现┌────────────────────────────────────────────────────────────┐ │ 模块化架构示意图 │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ application.yaml配置文件 │ │ │ │ │ │ │ │ storage: # 模块名 │ │ │ │ selector: elasticsearch # 选择这个实现 │ │ │ │ elasticsearch: # 具体配置 │ │ │ │ clusterNodes: ... │ │ │ └─────────────────────┬──────────────────────────────┘ │ │ │ 读取配置 │ │ ▼ │ │ ┌─────────────┐ ┌──────────────────────────────────┐ │ │ │ ModuleDefine │ │ ModuleProvider 实现库 │ │ │ │ (抽象接口) │ │ │ │ │ │ │ │ ┌──────────┐ ┌──────────────┐ │ │ │ │ storage模块 │←───→│ │ ES │ │ MySQL │ │ │ │ │ - DAO接口 │ │ │ Provider │ │ Provider │ │ │ │ │ - 查询接口 │ │ └──────────┘ └──────────────┘ │ │ │ └─────────────┘ └──────────────────────────────────┘ │ └────────────────────────────────────────────────────────────┘模块化的application.yaml用过SkyWalking的人都见过这个文件现在再看一遍会有不同理解# OAP Server的核心配置文件core:default:# default就是ModuleProvider的名字role:Mixed# 当前节点角色restHost:0.0.0.0restPort:12800storage:selector:${SW_STORAGE:elasticsearch}# 通过环境变量选择Providerelasticsearch:# ES Provider的配置namespace:${SW_NAMESPACE:}clusterNodes:${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}mysql:# MySQL Provider的配置如果selector选了mysql才生效metadataQueryMaxSize:${SW_STORAGE_MAX_QUERY_SIZE:5000}selector: elasticsearch这一行就是在告诉ModuleManager“对于storage这个模块请使用elasticsearch这个Provider的实现。”模块化带来的好处好处1随意替换实现你想换个存储后端改一行YAMLselector: mysql。你想换个集群协调器从ZooKeeper换到Nacos改一行YAMLselector: nacos。好处2二次开发不破坏原有代码如果你需要增加一个自定义功能比如对接公司内部的告警系统只需要实现一个新的Provider放到classpath里修改配置文件不需要动任何原有代码。这对企业内部定制化非常友好。好处3清晰的接口边界ModuleDefine定义了模块的接口边界不同团队可以分别开发不同模块的实现接口稳定后互不干扰。这是大型开源项目社区化协作的重要基础。模块依赖管理模块之间可以声明依赖关系OverridepublicString[]requiredModules(){// 声明这个模块依赖于哪些其他模块returnnewString[]{CoreModule.NAME,StorageModule.NAME};}OAP Server启动时会对模块依赖进行拓扑排序确保被依赖的模块先启动避免循环依赖。四、第三哲学轻量化设计放弃大数据技术栈这是SkyWalking最具争议性的设计决策也是它与Pinpoint最根本的区别。Pinpoint的选择基于HBase存储海量Trace数据利用其分布式存储能力。SkyWalking的选择自研轻量级流计算框架彻底抛弃HBase/HDFS等大数据技术栈。这个决策的逻辑链大数据技术栈的代价 运维复杂 → 需要专门的大数据团队 部署庞大 → HBase需要HDFSHDFS需要ZooKeeper... 启动时间长 → 从分钟级到小时级 APM系统的要求 轻量部署 → Ops团队能独立维护 快速启动 → 分钟内就绪 灵活存储 → 适应不同规模的团队 结论大数据技术栈不适合APM系统轻量化的实现手段手段1DataCarrier内存队列探针内部使用自研的DataCarrier内存队列而不是引入Kafka等重量级MQ。数据先在内存中缓冲然后异步批量发送这样既保证了业务线程的低延迟又避免了引入额外的中间件依赖。手段2OAL流式计算不用Storm/Flink等大数据流计算框架而是自研OAL可观测性分析语言和对应的流式计算引擎。这套计算引擎专为APM计算优化远比通用流计算框架轻量。手段3多存储后端支持通过标准化存储接口让用户选择适合自己规模的存储。小团队用MySQL就够了大团队上Elasticsearch。没有必须上HBase的强制要求。轻量化的效果┌─────────────────────────────────────────────────────────────┐ │ 轻量化设计对比SkyWalking vs Pinpoint │ ├──────────────────────┬────────────────┬────────────────────┤ │ 维度 │ SkyWalking │ Pinpoint │ ├──────────────────────┼────────────────┼────────────────────┤ │ 最小化部署 │ OAP ES/MySQL │ HBase HDFS ZK │ │ 存储技术 │ ES/MySQL/TiDB │ HBase(强依赖) │ │ 运维复杂度 │ 低 │ 高 │ │ 小团队可用性 │ ✅ │ ❌ │ │ 超大规模支持 │ 需要扩容ES │ HBase天然扩展 │ │ 社区活跃度 │ ⭐⭐⭐⭐⭐ │ ⭐⭐⭐ │ └──────────────────────┴────────────────┴────────────────────┘轻量化让SkyWalking能被所有规模的团队使用——从5人创业团队到几百服务的大厂都能找到适合自己的部署方案。五、三大哲学的内在联系三大设计哲学不是孤立的它们相互支撑、形成体系面向协议设计 ─────┐ ├─→ 让多语言探针、多存储后端、多UI实现成为可能 模块化设计 ─────┤ ├─→ 降低二次开发门槛支持企业内部定制 轻量化设计 ─────┘ 让小团队也能用上企业级APM能力 三者合力让SkyWalking既是开箱即用的APM工具 又是可深度定制的可观测性平台本篇小结SkyWalking的三大设计哲学面向协议设计探针协议gRPC和查询协议GraphQL预先定义多语言探针和多种UI实现基于同一套协议互通模块化设计Module Provider模式每个功能模块都可以通过配置替换不同实现支持企业定制化轻量化设计拒绝大数据技术栈自研轻量级流计算支持多种存储后端让不同规模的团队都能用理解这三大原则是后续深入学习SkyWalking源码和二次开发的重要前提。下一篇我们用具体数字说话SkyWalking的性能优势到底有多大为什么能比Pinpoint快那么多上一篇【第03篇】SkyWalking架构全景图——四大组件的前世今生下一篇【第05篇】SkyWalking凭啥比Pinpoint快——性能优势的深层原因