SkyWalking

Apache SkyWalking是一款使用广泛的开源应用性能监控(APM)系统,该项目由中国程序员吴晟于2015年创建,2019年成为Apache软件基金会顶级项目。SkyWalking采用无侵入式的探针技术,它能够自动采集分布式系统的调用链路、性能指标和日志数据,并提供了全栈式的可观测性解决方案,这可以极大的帮助开发者定位系统性能瓶颈和故障点。

项目官网:https://skywalking.apache.org/

现代服务端软件工程架构中APM的意义

在单体时代,一个请求的处理过程通常完整地发生在单个应用实例内,日志也都写在同一台机器上,出了问题翻日志就能找到原因。但到了微服务时代,一个用户请求可能跨越十几个服务、几十个节点,涉及数据库、缓存、消息队列等各种中间件,任何一个环节出了问题都可能导致请求失败,但你根本不知道是哪个环节出了问题。这就是可观测性(Observability)要解决的核心问题。它通常涵盖3个维度:

Traces(链路追踪):记录请求从入口到出口经过了哪些服务、每个服务耗时多少,方便快速定位性能瓶颈和错误位置。

Metrics(指标监控):采集服务的吞吐量、响应时间、错误率、JVM内存等数值型指标,通过时间序列展示系统的运行状态趋势。

Logs(日志关联):将应用日志与链路追踪数据关联起来,当发现某条链路有异常时可以直接跳转到该链路对应的日志记录。

APM(Application Performance Monitoring)全称指应用性能监控,它是一种对软件应用全链路性能进行采集、分析、告警、故障定位的技术体系。SkyWalking就是这样一款APM平台,它的核心能力包括以下几点:

分布式链路追踪:自动采集服务间调用关系生成完整调用链路图,支持HTTP、Dubbo、gRPC、Kafka等主流协议。

服务拓扑图:根据采集到的调用数据自动绘制服务依赖关系图,一点看全系统中各服务是如何互相调用的。

指标监控与告警:监控服务的SLA、响应时间分布、错误率等指标并可配置告警规则,在指标异常时通过Webhook或邮件通知。

日志与链路关联:将应用日志中的Trace ID与链路追踪数据打通,支持在UI上直接从链路跳转到对应日志。

多语言支持:除了Java,SkyWalking还提供了Python、Go、Node.js、.NET等语言的Agent或SDK,也支持OpenTelemetry协议接入。

简单来说,在复杂的微服务调用链中,当请求出现异常时,SkyWalking的链路追踪能让我们精准找到是哪个服务、哪个接口出了问题。通过链路数据和指标数据结合,我们可以发现哪个服务是整条链路的性能短板,这可以指导针对性的性能优化。此外,随着系统规模增长,服务间依赖关系往往变得混乱,SkyWalking的拓扑图可以可视化这些依赖,便于团队从全局角度对系统进行理解和治理。这就是SkyWalking存在的最大意义。

当然,SkyWalking也不是万能的,以Java体系为例,SkyWalking的Agent机制对JVM会产生3%~5%的性能开销,在极端低延迟场景是否要部署SkyWalking需要仔细权衡。此外SkyWalking存储数据通常还得引入Elasticsearch,这显然带来了额外的巨大运维成本。

SkyWalking架构

SkyWalking的整体架构由四个核心部分组成:Agent、OAP、Storage和UI。

Agent是嵌入在应用进程中的数据采集探针,以Java Agent为例,它在JVM启动时通过字节码增强技术自动拦截方法调用,采集Trace、Metrics等数据,然后通过gRPC或HTTP协议将数据上报给OAP服务。

OAP(Observability Analysis Platform)是SkyWalking的服务端核心,它负责接收Agent上报的数据并进行聚合分析,得出P99响应时间、错误率等指标数据,并将结果持久化到存储层。实际生产环境中,OAP通常采用集群部署以提升系统吞吐能力。

Storage是存储层,它负责持久化所有的链路数据、指标数据等。SkyWalking支持多种存储后端,其中Elasticsearch是最常见的选择,此外还支持SkyWalking官方自研的BanyanDB,以及MySQL、PostgreSQL等关系型数据库。

UI是SkyWalking自带的前端界面,它通过访问OAP提供的API展示链路、拓扑、指标、告警等各类数据,提供了完整的可视化能力。

Trace、Span与Service

链路追踪中有一些基本概念和术语,在具体学习SkyWalking之前我们需要简单了解。

Service 服务:服务是一个逻辑概念,它对应一个部署的应用或微服务,例如order-serviceuser-service等。SkyWalking通过Agent配置的服务名来区分不同的服务。

Service Instance 服务实例:服务实例是服务的具体运行节点,同个服务可能部署了多个实例,例如order-service水平扩容部署了3个Pod,每个实例都会单独展示在SkyWalking中。

Endpoint 端点:端点是服务对外暴露的操作单元,例如一个HTTP接口GET /api/order/{id}或者一个RPC方法,SkyWalking中会聚合展示每个Endpoint的请求量、响应时间等指标。

Trace 链路:链路代表一次完整的请求调用过程,从请求入口到最终响应跨越的所有服务调用共同构成一条Trace。每条Trace都有全局唯一的Trace ID。

Span 跨度:跨度是Trace中的最小工作单元,它代表一次具体的操作,例如一次HTTP调用、一次数据库查询、一次Redis读取。一条Trace由多个Span组成,Span之间通过父子关系形成树形结构。

这里我们用一个例子来说明Trace和Span的关系。用户在电商APP上点击“提交订单”,这触发了一次请求,这次请求就是一条Trace;请求先到达order-service,这是一个Span;order-service查询了数据库,这又是一个子Span;order-service调用了inventory-service扣减库存,这又是另一个子Span,inventory-service查询了Redis又形成了Span,以此类推。

graph TD
    T["Trace ID: abc-123"]
    S1["Span: order-service 接收HTTP请求<br/>耗时: 120ms"]
    S2["Span: order-service 查询MySQL<br/>耗时: 30ms"]
    S3["Span: 调用 inventory-service<br/>耗时: 50ms"]
    S4["Span: inventory-service 查询Redis<br/>耗时: 5ms"]

    T --> S1
    S1 --> S2
    S1 --> S3
    S3 --> S4

搭建SkyWalking

本地学习和测试时,我们可以直接用Docker搭建SkyWalking OAP和UI服务。此外SkyWalking的运行依赖存储后端,这里我们使用Elasticsearch作为存储。如果你不熟悉Elasticsearch,可以参考笔记仓库的软件工程/数据库系统/Elasticsearch相关章节。

SkyWalking和Elasticsearch之间要互相访问,因此首先我们创建网络。

docker network create elastic-net

然后部署Elasticsearch服务。

docker run -d --name elasticsearch --net elastic-net -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=false" -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" elasticsearch:8.13.4

最后我们部署SkyWalking OAP和UI服务。

docker run -d --name skywalking-oap --network elastic-net -p 11800:11800  -p 12800:12800  -e SW_STORAGE=elasticsearch  -e SW_STORAGE_ES_CLUSTER_NODES=elasticsearch:9200  apache/skywalking-oap-server:10.1.0
docker run -d --name skywalking-ui --network elastic-net -p 8080:8080 -e SW_OAP_ADDRESS=http://skywalking-oap:12800 apache/skywalking-ui:10.1.0

SkyWalking OAP中11800是接收Agent上报的端口,12800是OAP对外提供HTTP查询API的端口,UI也通过这个端口和OAP通信。

OAP首次启动时需要在Elasticsearch中初始化索引结构,这个过程可能需要一点时间,期间UI可能无法正常加载。等待所有容器启动并初始化完成后,我们打开浏览器访问http://localhost:8080即可看到SkyWalking UI界面。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。