8

微服务链路追踪组件Skywalking实战 - InfoQ 写作平台

 2 years ago
source link: https://xie.infoq.cn/article/9ed9c65315251d0b39614d4d0
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1. skywalking 是什么

对于一个大型的几十个、几百个微服务构成的微服务架构系统,通常会遇到下面一些问题,比如:

  1. 如何串联整个调用链路,快速定位问题?

  2. 如何理清各个微服务之间的依赖关系?

  3. 如何进行各个微服务接口的性能分折?

  4. 如何跟踪整个业务流程的调用处理顺序?

skywalking 是一个国产开源框架,2015 年由吴晟开源 , 2017 年加入 Apache 孵化器。skywalking 是分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计。SkyWalking 是观察性分析平台和应用性能管理系统,提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。

官网:http://skywalking.apache.org/

下载:http://skywalking.apache.org/downloads/

调用链选型

  1. Zipkin 是 Twitter 开源的调用链分析工具,目前基于 springcloud sleuth 得到了广泛的使用,特点是轻量,使用部署简单。

  2. Pinpoint 是韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI 功能强大,接入端无代码侵入。

  3. SkyWalking 是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI 功能较强,接入端无代码侵入。目前已加入 Apache 孵化器。

  4. CAT 是大众点评开源的基于编码和配置的调用链分析,应用监控分析,日志采集,监控报警等一系列的监控平台工具。

探针性能对比

模拟了三种并发用户:500,750,1000。使用 jmeter 测试,每个线程发送 30 个请求,设置思考时间为 10ms。使用的采样率为 1,即 100%,这边与生产可能有差别。pinpoint 默认的采样率为 20,即 50%,通过设置 agent 的配置文件改为 100%。zipkin 默认也是 1。组合起来,一共有 12 种。下面看下汇总表:

从上表可以看出,在三种链路监控组件中,skywalking 的探针对吞吐量的影响最小,zipkin 的吞吐量居中。pinpoint 的探针对吞吐量的影响较为明显,在 500 并发用户时,测试服务的吞吐量从 1385 降低到 774,影响很大。然后再看下 CPU 和 memory 的影响,在内部服务器进行的压测,对 CPU 和 memory 的影响都差不多在 10%之内。

1.1 Skywalking 主要功能特性

1、多种监控手段,可以通过语言探针和 service mesh 获得监控的数据;

2、支持多种语言自动探针,包括 Java,.NET Core 和 Node.JS;

3、轻量高效,无需大数据平台和大量的服务器资源;

4、模块化,UI、存储、集群管理都有多种机制可选;

5、支持告警;

6、优秀的可视化解决方案;

1.2 Skywalking 整体架构

整个架构分成四部分:

1、上部分 Agent :负责从应用中,收集链路信息,发送给 SkyWalking OAP 服务器;

2、下部分 SkyWalking OAP :负责接收 Agent 发送的 Tracing 数据信息,然后进行分析(Analysis Core),存储到外部存储器(Storage),最终提供查询(Query)功能;

3、右部分 Storage:Tracing 数据存储,目前支持 ES、MySQL、Sharding Sphere、TiDB、H2 多种存储器,目前采用较多的是 ES,主要考虑是 SkyWalking 开发团队自己的生产环境采用 ES 为主;

4、左部分 SkyWalking UI:负责提供控制台,查看链路等等;

SkyWalking 支持三种探针:

● Agent – 基于 ByteBuddy 字节码增强技术实现,通过 jvm 的 agent 参数加载,并在程序启动时拦截指定的方法来收集数据。

● SDK – 程序中显式调用 SkyWalking 提供的 SDK 来收集数据,对应用有侵入。

● Service Mesh – 通过 Service mesh 的网络代理来收集数据。

后端(Backend)

接受探针发送过来的数据,进行度量分析,调用链分析和存储。后端主要分为两部分:

● OAP(Observability Analysis Platform)- 进行度量分析和调用链分析的后端平台,并支持将数据存储到各种数据库中,如:ElasticSearch,MySQL,InfluxDB 等。

● OAL(Observability Analysis Language)- 用来进行度量分析的 DSL,类似于 SQL,用于查询度量分析结果和警报。

界面(UI)

● RocketBot UI – SkyWalking 7.0.0 的默认 web UI

● CLI – 命令行界面

这三个模块的交互流程:

1.3 SkyWalking 环境搭建部署

  • skywalking agent 和业务系统绑定在一起,负责收集各种监控数据

  • Skywalking oapservice 是负责处理监控数据的,比如接受 skywalking agent 的监控数据,并存储在数据库中;接受 skywalking webapp 的前端请求,从数据库查询数据,并返回数据给前端。Skywalking oapservice 通常以集群的形式存在。

  • skywalking webapp,前端界面,用于展示数据。

  • 用于存储监控数据的数据库,比如 mysql、elasticsearch 等。

1.3.1 下载 SkyWalking

下载:http://skywalking.apache.org/downloads/

目录结构

1.3.2 搭建 SkyWalking OAP 服务

先使用默认的 H2 数据库存储,不用修改配置

config/application.yml

启动脚本 bin/startup.sh

日志信息存储在 logs 目录

启动成功后会启动两个服务,一个是 skywalking-oap-server,一个是 skywalking-web-ui

skywalking-oap-server 服务启动后会暴露 11800 和 12800 两个端口,分别为收集监控数据的端口 11800 和接受前端请求的端口 12800,修改端口可以修改 config/applicaiton.yml

skywalking-web-ui 服务会占用 8080 端口, 修改端口可以修改 webapp/webapp.yml

server.port:SkyWalking UI 服务端口,默认是 8080;

collector.ribbon.listOfServers:SkyWalking OAP 服务地址数组,SkyWalking UI 界面的数据是通过请求 SkyWalking OAP 服务来获得;

访问:http://192.168.3.100:8080/

页面的右下角可以中英文切换,可以切换选择要展示的时间区间的跟踪数据。

1.4 SkyWalking 中三个概念

服务(Service) :表示对请求提供相同行为的一系列或一组工作负载,在使用 Agent 时,可以定义服务的名字;

服务实例(Service Instance) :上述的一组工作负载中的每一个工作负载称为一个实例, 一个服务实例实际就是操作系统上的一个真实进程;

端点(Endpoint) :对于特定服务所接收的请求路径, 如 HTTP 的 URI 路径和 gRPC 服务的类名 + 方法签名;

2. SkyWalking 快速开始

2.1 SkyWalking Agent 跟踪微服务

2.1.1 通过 jar 包方式接入

准备一个 springboot 程序,打成可执行 jar 包,写一个 shell 脚本,在启动项目的 Shell 脚本上,通过 -javaagent 参数进行配置 SkyWalking Agent 来跟踪微服务;

startup.sh 脚本:

#!/bin/sh# SkyWalking Agent配置export SW_AGENT_NAME=springboot-skywalking-demo #Agent名字,一般使用`spring.application.name`export SW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800 #配置 Collector 地址。export SW_AGENT_SPAN_LIMIT=2000 #配置链路的最大Span数量,默认为 300。export JAVA_AGENT=-javaagent:/usr/local/soft/apache-skywalking-apm-bin-es7/agent/skywalking-agent.jarjava $JAVA_AGENT -jar springboot-skywalking-demo-0.0.1-SNAPSHOT.jar #jar启动
java -javaagent:/usr/local/soft/apache-skywalking-apm-bin-es7/agent/skywalking-agent.jar -DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800 -DSW_AGENT_NAME=springboot-skywalking-demo -jar springboot-skywalking-demo-0.0.1-SNAPSHOT.jar

参数名对应 agent/config/agent.config 配置文件中的属性。

属性对应的源码:org.apache.skywalking.apm.agent.core.conf.Config.java

# The service name in UIagent.service_name=${SW_AGENT_NAME:Your_ApplicationName}# Backend service addresses.collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800}

我们也可以使用 skywalking.+配置文件中的配置名作为系统配置项来进行覆盖。 javaagent 参数配置方式优先级更高

-javaagent:D:\apache\apache-skywalking-apm-es7-8.4.0\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar-Dskywalking.agent.service_name=springboot-skywalking-demo-Dskywalking.collector.backend_service=192.168.3.100:11800

测试: http://192.168.3.100:8000/user/list

在启动程序前加一个-javaagent 参数即可完成对程序的跟踪

2.1.2 在 IDEA 中使用 Skywalking

在运行的程序配置 jvm 参数,如下图所示:

# skywalking-agent.jar的本地磁盘的路径-javaagent:D:\apache\apache-skywalking-apm-es7-8.4.0\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar# 在skywalking上显示的服务名-DSW_AGENT_NAME=springboot-skywalking-demo# skywalking的collector服务的IP及端口-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.3.100:11800 

2.1.3 Skywalking 跨多个微服务跟踪

Skywalking 跨多个微服务跟踪,只需要每个微服务启动时添加 javaagent 参数即可。

启动微服务 mall-gateway,mall-order,mall-user ,配置 skywalking 的 jvm 参数

http://localhost:8888/user/findOrderByUserId/1

注意:此处存在 bug,跟踪链路不显示 gateway

拷贝 agent/optional-plugins 目录下的 gateway 插件到 agent/plugins 目录

2.2 Skywalking 告警通知

skywalking 告警的核心由一组规则驱动,这些规则定义在 config/alarm-settings.yml 文件中,告警规则的定义分为三部分:

1、告警规则:它们定义了应该如何触发度量警报,应该考虑什么条件;

2、网络钩子(Webhook}:当警告触发时,哪些服务终端需要被通知;

3、gRPC 钩子:远程 gRPC 方法的主机和端口,告警触发后调用;

为了方便,skywalking 发行版中提供了默认的 alarm-setting.yml 文件,包括一些规则,每个规则有英文注释,可以根据注释得知每个规则的作用:

  • 在最近 10 分钟的 3 分钟内服务平均响应时间超过 1000ms

  • 最近 10 分钟内,服务成功率在 2 分钟内低于 80%

  • 服务实例的响应时间在过去 10 分钟的 2 分钟内超过 1000ms

  • 数据库访问{name}的响应时间在过去 10 分钟的 2 分钟内超过 1000ms

只要我们的服务请求符合 alarm-setting.yml 文件中的某一条规则就会触发告警。

比如 service_resp_time_rule 规则:

该规则表示服务{name}的响应时间在最近 10 分钟的 3 分钟内超过 1000ms;

编写接口,模拟慢查询

@RequestMapping("/info/{id}")public User info(@PathVariable("id") Integer id){    try {        Thread.sleep(2000);    } catch (InterruptedException e) {        e.printStackTrace();    }    return userService.getById(id);}
@RequestMapping("/notify")public String notify(@RequestBody Object obj){    //TODO 告警信息,给技术负责人发短信,钉钉消息,邮件,微信通知等    System.err.println(obj.toString());    return "notify successfully";}

在 config/alarm-settings.yml 中配置回调接口,并重启 skywalking 服务

测试访问:http://localhost:8000/user/info/1,满足告警规则后,控制台输出告警信息

SkyWalking UI 显示告警信息

参考: https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/backend-alarm.md

对接钉钉:

Webhook 回调通知

SkyWalking 告警 Webhook 回调要求接收方是一个 Web 容器(比如 tomcat 服务),告警的消息会通过 HTTP 请求进行发送, 请求方法为 POST, Content-Type 为 application/json, JSON 格式基于 List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage>的集合对象数据, 集合中的每个 AlarmMessage 包含以下信息:

1、scopeId. 所有可用的 Scope,参考:org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;

2、name. 目标 Scope 的实体名称;

3、id0. Scope 实体的 ID;

4、id1. 未使用;

5、ruleName. 在 alarm-settings.yml 中配置的规则名;

6、alarmMessage. 报警消息内容;

7、startTime. 告警时间, 位于当前时间与 UTC 1970/1/1 之间;

[{	scopeId = 2,	scope = SERVICE_INSTANCE,	name = 98e1839 a6fdf48b0aedb0ecabb8ea5f7 @192 .168 .233 .1 of springboot - skywalking - demo,	id0 = c3ByaW5nYm9vdC1za3l3YWxraW5nLWRlbW8 = .1 _OThlMTgzOWE2ZmRmNDhiMGFlZGIwZWNhYmI4ZWE1ZjdAMTkyLjE2OC4yMzMuMQ == ,	id1 = ,	ruleName = service_instance_resp_time_rule,	alarmMessage = Response time of service instance 98e1839 a6fdf48b0aedb0ecabb8ea5f7 @192 .168 .233 .1 of springboot - skywalking - demo is more than 1000 ms in 2 minutes of last 10 minutes,	startTime = 1613913565462}, {	scopeId = 6,	scope = ENDPOINT_RELATION,	name = User in User to / user / info / {		id	} in springboot - skywalking - demo,	id0 = VXNlcg == .0 _VXNlcg == ,	id1 = c3ByaW5nYm9vdC1za3l3YWxraW5nLWRlbW8 = .1 _L3VzZXIvaW5mby97aWR9,	ruleName = endpoint_relation_resp_time_rule,	alarmMessage = Response time of endpoint relation User in User to / user / info / {		id	} in springboot - skywalking - demo is more than 1000 ms in 2 minutes of last 10 minutes,	startTime = 1613913565462}]

2.3 Skywalking 持久化跟踪数据

2.3.1 基于 mysql 持久化

1. 修改 config 目录下的 application.yml,使用 mysql 作为持久化存储的仓库

2. 修改 mysql 连接配置

storage:  #选择使用mysql   默认使用h2,不会持久化,重启skyWalking之前的数据会丢失  selector: ${SW_STORAGE:mysql}  #使用mysql作为持久化存储的仓库  mysql:    properties:      #数据库连接地址      jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://1ocalhost:3306/swtest"}      #用户名      dataSource.user: ${SW_DATA_SOURCE_USER:root}      #密码      dataSource.password: ${SW_DATA_SOURCE_PASSWORD:root}

注意:需要添加 mysql 数据驱动包,因为在 lib 目录下是没有 mysql 数据驱动包的,所以修改完配置启动是会报错,启动失败的。

3. 添加 mysql 数据驱动包到 oap-libs 目录下

4. 启动 Skywalking

查看 swtest 数据库,可以看到生成了很多表。

说明启动成功了,打开配置对应的地址http://192.168.3.100:8080/,可以看到 skywalking 的 web 界面。

测试:重启 skywalking,验证跟踪数据会不会丢失

2.3.2 基于 elasticsearch 持久化

1.准备好 elasticsearch 环境

启动 elasticsearch 服务

su - escd /usr/local/soft/elasticsearch-7.6.1/bin/elasticsearch -d

启动 elasticsearch-head 服务,访问http://192.168.3.100:9100

cd /usr/local/soft/elasticsearch-head/node_modules/gruntnohup bin/grunt server &

2.修改 config/application.yml 配置文件

修改 elasticsearch7 的连接配置

3. 启动 Skywalking 服务

启动时会向 elasticsearch 中创建大量的 index 索引用于持久化数据,每天会产生一个新的索引文件。

启动应用程序,查看跟踪数据是否已经持久化到 elasticsearch 的索引中,然后重启 skywalking,验证跟踪数据会不会丢失

2.4 自定义 SkyWalking 链路追踪

如果我们希望对项目中的业务方法,实现链路追踪,方便我们排查问题,可以使用如下的代码

<!-- SkyWalking 工具类 --><dependency>    <groupId>org.apache.skywalking</groupId>    <artifactId>apm-toolkit-trace</artifactId>    <version>8.4.0</version></dependency>

在业务方法中可以 TraceContext 获取到 traceId

@RequestMapping("/list")public List<User> list(){    //TraceContext可以绑定key-value    TraceContext.putCorrelation("name", "fox");    Optional<String> op = TraceContext.getCorrelation("name");    log.info("name = {} ", op.get());    //获取跟踪的traceId    String traceId = TraceContext.traceId();    log.info("traceId = {} ", traceId);    return userService.list();}

测试 http://localhost:8000/user/list

在 Skywalking UI 中查询 tranceId

2.4.1 @Trace 将方法加入追踪链路

如果一个业务方法想在 ui 界面的跟踪链路上显示出来,只需要在业务方法上加上 @Trace 注解即可

2.4.2 加入 @Tags 或 @Tag

我们还可以为追踪链路增加其他额外的信息,比如记录参数和返回信息。实现方式:在方法上增加 @Tag 或者 @Tags。

@Trace@Tag(key = "list", value = "returnedObj")public List<User> list(){    return userMapper.list();}@Trace@Tags({@Tag(key = "param", value = "arg[0]"),        @Tag(key = "user", value = "returnedObj")})public User getById(Integer id){    return userMapper.getById(id);}

2.5 Skywalking 集成日志框架

logback官方配置

log4j官方配置

log4j2j官方配置

<!-- apm-toolkit-logback-1.x --><dependency>    <groupId>org.apache.skywalking</groupId>    <artifactId>apm-toolkit-logback-1.x</artifactId>    <version>8.4.0</version></dependency>

添加 logback-spring.xml 文件,并配置 %tid 占位符

Skywalking 通过 grpc 上报日志 (需要 v8.4.0)

gRPC 报告程序可以将收集到的日志转发到 SkyWalking OAP 服务器上

logback-spring.xml 中添加

 <!-- v8.4.0提供 --> <appender name="grpc-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"/><root level="info">    <appender-ref ref="grpc-log" /></root>

打开 agent/config/agent.config 配置文件,添加如下配置信息:

plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:192.168.3.100}plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}plugin.toolkit.log.grpc.reporter.max_message_size=${SW_GRPC_LOG_MAX_MESSAGE_SIZE:10485760}plugin.toolkit.log.grpc.reporter.upstream_timeout=${SW_GRPC_LOG_GRPC_UPSTREAM_TIMEOUT:30}

以上配置是默认配置信息,agent 与 oap 在本地的可以不配

agent配置信息大全

Skywalking UI 效果

此处日期格式存在问题

https://github.com/apache/skywalking-rocketbot-ui/pull/428

2.6 Skywalking 集群部署

Skywalking 集群是将 skywalking oap 作为一个服务注册到 nacos 上,只要 skywalking oap 服务没有全部宕机,保证有一个 skywalking oap 在运行,就能进行跟踪。

搭建一个 skywalking oap 集群需要:

(1)至少一个 Nacos(也可以是 nacos 集群)

(2)至少一个 ElasticSearch(也可以是 es 集群)

(3)至少 2 个 skywalking oap 服务;

(4)至少 1 个 UI(UI 也可以集群多个,用 Nginx 代理统一入口)

1.修改 config/application.yml 文件

使用 nacos 作为注册中心

修改 nacos 配置

可以选择性修改监听端口

修改存储策略,使用 elasticsearch7 作为 storage

2. 配置 ui 服务 webapp.yml 文件的 listOfServers,写两个地址

3.启动服务测试

启动 Skywalking 服务,指定 springboot 应用的 jvm 参数

-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.3.10:11800,192.168.3.12:11800

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK