SkyWalking 是一个开源 APM 系统,包括针对 Cloud Native 体系结构中的分布式系统的监视,跟踪,诊断功能。核心功能如下:
- 服务、服务实例、端点指标分析
- 根本原因分析,在运行时分析代码
- 服务拓扑图分析
- 服务,服务实例和端点依赖性分析
- 检测到慢速服务和端点
- 性能优化
- 分布式跟踪和上下文传播
- 数据库访问指标。检测慢速数据库访问语句(包括 SQL 语句)
- 报警
SkyWalking 目前是 Apache 顶级项目,作为这么优秀的开源项目,它的架构设计理念肯定会有很多值得我们借鉴。
SkyWalking 整体架构设计
SkyWalking 的整体架构设计,官方是有比较粗的架构图,那个我在这里就不展示了,如果是熟悉 SkyWalking,看那个就很清晰,但是如果不熟悉,就很难知道整体工程是如何构架的,那么我会从整体工程的角度去剖析整体架构设计。
植入到宿主应用的功能模块包括:apm-agent、apm-agent-core、apm-sdk-plugin、bootstrap-plugins 和 optional-plugins。
探针通过字节码框架 bytebuddy,在运行期间植入到业务的静态类、实例类的静态方法和静态方法中,完成链路追踪。
探针生态是全链路监控的一个很重要的指标,那么 Skywalking 又具备哪些探针。
Skywalking 正式通过比较全面的探针覆盖率来完成对业务应用的全量侵入,达到对性能指标可观察的目的,这个也是 Skywalking 的最大亮点之一。
在 Skywalking 中,探针是指集成到目标系统中的代理或 SDK 库,负责收集包括跟踪和度量在内的遥测数据。基于目标系统技术堆栈,探针可以使用非常不同的方式来实现此目的。但最终它们是相同的,只是收集和重新格式化数据,然后发送到 OAP 平台。
探针总共分为三类:
1. 基于语言的本地代理
这种代理运行在目标服务用户空间中,就像用户代码的一部分。例如 SkyWalking Java agent。
2. 服务网格探针
服务网格探针从服务网格或代理中的侧车、控制面板收集数据。在过去,proxy 只被用作整个集群的入口,但是有了 Service Mesh 和 sidecar,现在我们可以在此基础上进行观察。
3. 第三方工具库
SkyWalking 可以融合其他分布式链路追踪的存储数据结构(只要是符合 opentracing 规范的)。它对数据进行分析,将其转换为 trace、度量或两者兼用的格式。目前能够兼容 Zipkin span 的全链路数据。
OAP(可观测分析平台),是 SkyWalking 对整个后端的一个简称,注意 SkyWalking 是把自己定义为为一个可观察性的应用平台和解决业务业务性能问题的一个工具,所以才有了 OAP 平台的概念。
OAP 平台接受来自更多来源的数据,大致分为两大领域能力:
- Trace。包括 SkyWalking 原生数据格式。Zipkin v1、v2 数据格式和 Jaeger 数据格式。
- Metrics。与 Istio、Envoy、Linkerd 等服务网格平台集成,提供数据面板或控制面板的可观测性。另外,SkyWalking 本机代理可以以度量模式运行,这可以极大地提高性能。
SkyWalking 官方 UI 为 SkyWalking 观察分布式集群提供了默认的、强大的可视化功能。
Dashboard 提供服务、服务实例和端点的度量,具体提供吞吐量 CPM,表示每分钟的调用。响应时间百分位数,包括 p99、p95、p90、p75、p50。在维基上阅读百分位数 SLA 表示成功率。对于 HTTP,它意味着 200 个响应码的速率。
SkyWalking 存储端架构设计
存储端架构设计,我们就从 SkyWalking 的存储领域模型来分析。
存储领域的边界,在 SkyWalking 中式通过插件模块来隔离的,具体是通过选择器来实现组件隔离,什么是选择器,其实在 SkyWalking 中就是在配置文件中,业务可以通过一个配置参数来控制平台是启用哪一个插件来完成存储,这样是不是很方便。
在配置文件 application.yml 中,通过 selector 属性来控制 OAP 平台启动的存储插件。
代码语言:javascript复制storage:
selector: ${SW_STORAGE:h2}
1. 启动加载配置 loadConfig,判断功能模块是否开启了 SELECTOR。
2. 开启了 SELECTOR,就会在配置加载的过程中剔除掉多余的插件模块,比如存储端配置了 selector 为 h2,那么就会剔除其他的存储插件的配置。
配置文件中就剩下我们需要的模块了,然后通过 ModuleManager,按需加载和初始化模块。这样存储模块之间在代码启动阶段就做到了依据配置文件来实现启动隔离的目的。
ModuleDefine 和 ModuleProvider 根据配置完成映射,并通过通用模块加载功能,完成按需加载。
common 模块:
- Es7DAO:功能的作用域-elasticSearch 的 DAO 的适配类。
- StorageModuleElasticsearch7Provider:功能的作用域,继承 org.apache.skywalking.oap.server.library.module.ModuleProvider,这个类两个核心方法是 prepare() 和 start()。prepare() 方法会初始化 ElasticSearch7Client 客户端,向模块注册 elasticSearch 的 DAO 服务,服务会存储在 ModuleProvider.services 中,services 是一个 HashMap。
- StorageModuleElasticsearch7Config:功能的作用域,执行 StorageModuleElasticsearch7Provider.prepare() 和 start() 方法时,需要很多关于 elasticSearch 存储的全局配置,配置信息就会从 StorageModuleElasticsearch7Config 中获取。
client 模块:
- ElasticSearch7Client:功能作用域,适配了旧版本的 ElasticSearchClient,封装了能力 connect()、createIndex()、deleteIndex()、retrievalIndexByAliases()、createTemplate()、search()、prepareInsert()、prepareUpdate()、forceUpdate() 等,这些方法基本覆盖了基于 elasticSearch 存储的 CRUD 操作。
- ElasticSearch7InsertRequest:功能作用域-继承 org.elasticsearch.action.index.IndexRequest,这个是 elasticSearch 的一个公共 API,在 ElasticSearch7Client 的 prepareInsert 方法中会返回 ElasticSearch7InsertRequest.source() 构造的 InsertRequest 对象,其实了就是包装针对 ES 的索引操作。
- ElasticSearch7UpdateRequest:功能作用域,继承 org.elasticsearch.action.update.UpdateRequest,也会在 ElasticSearch7Client 的 prepareUpdate() 方法会构造 UpdateRequest 对象,来连接 elasticSearch 底层。
base 模块:
- StorageEs7Installer:功能作用域,继承 StorageEsInstaller 类,这个是低版本的一个 API,当然也是会了做适配。这个类的主要领域功能是:连接 ElasticSearch7InsertRequest 和存储,主要是用于 createMapping、createTable、createSetting 等,这些其实都是与索引相关。
dao 模块:
- MetricsEs7DAO:功能作用域,适配 MetricsEsDAO,主要封装基于度量指标的 DAO 类,multiGet、prepareBatchInsert、prepareBatchUpdate。
- StorageEs7DAO:功能作用域,主要封装基于存储的 DAO 类,包括:newMetricsDao、newRegisterDao、newRecordDao 和 newNoneStreamDao。
query 模块:
- AggregationQueryEs7DAO:功能作用域,适配 AggregationQueryEsDAO,这个是聚合器查询的 DAO 模块。
- AlarmQueryEs7DAO:功能作用域-适配 IAlarmQueryDAO,这个是告警查询的 DAO 模块。
- LogQueryEs7DAO 功能作用域-适配 ILogQueryDAO,这个是日志查询的 DAO 模块。
- MetadataQueryEs7DAO:功能作用域,适配 MetadataQueryEsDAO,这个是元数据查询的 DAO 模块。
- MetricsQueryEs7DAO:功能作用域,适配 MetricsQueryEsDAO,这个是度量指标查询的 DAO 模块。
- ProfileThreadSnapshotQueryEs7DAO:功能作用域,适配 ProfileThreadSnapshotQueryEsDAO,这个是线程快照查询的 DAO 模块。
- TraceQueryEs7DAO:功能作用域,适配 TraceQueryEsDAO,这个是链路数据查询的 DAO 模块。
cache 模块:
- EndpointInventoryCacheEs7DAO:功能作用域,适配 EndpointInventoryCacheEsDAO,基于 Endpoint 的资产缓存 DAO。
- NetworkAddressInventoryCacheEs7DAO:功能作用域,适配 NetworkAddressInventoryCacheEsDAO,基于 NetworkAddress 的资产缓存 DAO。
- ServiceInstanceInventoryCacheEs7DAO:功能作用域,适配 ServiceInstanceInventoryCacheDAO,基于 ServiceInstance 的资产缓存 DAO。
- ServiceInventoryCacheEs7DAO:功能作用域,适配 ServiceInventoryCacheEsDAO,基于 Service 的资产缓存 DAO。
存储模块的代码结构如下:
记一次完整的 SkyWalking 落地业务的实战
业务痛点
共享业务中心已经成型,微服务化改造已经按照规划,从 0-1 在拆分,但是服务之间解耦之后,很多调用关系就很难维护,并且服务拆分之后,服务之间调用由以前的一次 RPC 到微服务化之后的多次 RPC,这样服务之间的可观察性和性能监控非常重要,这样就需要有这么一套分布式链路追踪系统来为共享业务中心服务,以及为后续的业务中台做准备。
技术选型
技术选型是一个非常艰难的过程,记得是在 2018 年,那个时候阿里的鹰眼平台才刚在云栖大会上公布,所有人都对分布式链路追踪非常陌生,当然也有很多前沿的技术人,在实践这款,那个时候开源的分布式链路追踪技术还不是那么的成熟。
目前技术选型的框架如下:
- Appdash
- Lightstep
- Jaeger
- Skywalking
- Openzipkin
- Pinpoint
- Spring Cloud Sleuth
- Cat
- 阿里的鹰眼
- sofa-tracer
- …………
因为本文不是一篇技术选型的文章,但是为什么我们会选择 SkyWalking?这里就简单地分析下:
- 遵守 OpenTracing 规范
- 开源社区非常活跃
- Apache 顶级项目
- 探针覆盖率非常高’
- 插件化架构
- 丰富的 UI 拓扑资源
- 适配其他的分布式链路追踪系统,比如 Jaeger 和 Openzipkin
- 链路追踪性能损耗非常低
落地过程描述
1. 版本确认
因为要使用开源的框架,我们第一步就要确认稳定版本,然后开始 review 代码,这个阶段主要聚焦在整体的架构以及服务模块的边界上。
2. 测试环境采坑
测试环境接入一批边缘业务,验证链路的完整性以及一些不熟悉的功能,然后反馈社区,
社区的力量来完善框架,比如那个时候我们就通过这种方式,间接推动了 UI 的升级,才有了现在的比较高大尚的 UI 界面。
3. 预发布环境的引流
SkyWalking 接入到预发布环境之后,这样就能借助这个平台去监控准线上环境的流量,并且还可以通过这个平台去布道和宣讲,让业务负责人,有兴趣去接入这个系统,从而扩散它的优势。
4. 线上环境接入
接入线上环境之后,那么 SkyWalking 就在公司落地了,但是光落地肯定是不行的,因为我们要能维护,并且能够最大化的利用这个平台的价值,并为业务提效。
5. 充分利用 SkyWalking,并工具化
基于 SkyWalking 的告警平台设计、基于 SkyWalking 的服务等级协议设计、基于 SkyWalking 的业务链路依赖关系的设计等等,这个都是能够快速的为业务提效的能力,并且也都是 SkyWalking 能够工具化之后带来的能力。
6. 反哺社区
因为利用了开源来微公司的业务服务,我们也要反哺社区,这样这个生态就会更加丰富。
总结
SkyWalking 是一款非常优秀的分布式链路追踪系统,具备极强的分布式能力和代码诊断能力,并且对业务是零侵入,非常灵活。在这里,我强烈地推荐大家布道这款国产的 Apache 顶级项目,并逐步完善这个生态体系,丰富它在 CNCF 体系中的角色能力。
本文是作者 review 源码之后结合自己落地之后的一些心得,也许会有些不完善,但也是作者的心血,欢迎支持原创。