链路追踪介绍:
对于一个大型的几十个、几百个微服务构成的微服务架构系统,通常会遇到一些问题,比如:
- 如何串联整个调用链路,快速定位问题?
- 如何缕清各个微服务之间的依赖关系?
- 如何进行各个微服务接口的性能分析?
- 如何跟踪整个业务流程的调用处理顺序?
skywalking介绍
skywalking是一个国产开源框架,2017年加入 apache孵化器。skywalking是分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docket、k8s、Mesos)架构而设计。它是一款优秀的APM(Application Performance Management)工具,包括了分布式追踪、性能指标分析、应用和服务依赖分析等。
链路追踪框架对比:
1.Zipkin是Twitter开源的调用链分析工具,目前基于springcloud sleuth得到了广泛的使用,特点是轻量,使用部署简单。
2.Pinpoint是韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能强大,接入端无代码侵入。
3.SkyWalking是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多种插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器
4.CAT是大众点评开源的基于编码和配置的调用链分析,应用监控分析,日志采集,监控报警等一系列的监控平台工具。
项目 | Cat | Zipkin | Skywalking |
调用链可视化 | 有 | 有 | 有 |
聚合报表 | 非常丰富 | 少 | 较丰富 |
服务依赖图 | 简单 | 简单 | 好 |
埋点方式 | 侵入式 | 侵入式 | 非侵入,字节码增强 |
VM监控图标 | 好 | 无 | 有 |
支持语言 | java/.net | 丰富 | java/.net/node.js/php/go |
存储机制 | mysql(报表)、本地文件/HDFS(调用链) | 内存、es、mysql等 | H2、es |
社区支持 | 主要在国内 | 国外主流 | Apache支持 |
使用案例 | 美团、携程、陆金所 | 京东、阿里定制后不开源 | 华为、小米、当担、微众银行 |
APM | 是 | 否 | 是 |
开发基础 | eBay cal | Google Dapper | Google Dapper |
是否支持webflux | 否 | 是 | 是 |
Github stats(2019.12) | 12.3k | 12.2k | 11.8k |
性能对比:
模拟了三种并发用户:500,750,1000。使用jmeter测试,每个线程发送30个请求,设置思考时间为10ms。使用的采样率为1,即100%,这边与生产可能有差别。pinpoint默认的采样率为20,即50%,通过设置agent的配置文件改为100%,zipkin默认也是1,组合起来,一共12种:
从上表可以看出,在三种链路监控组件中,skywalking的探针对吞吐量的影响最小,zipkin的吞吐量居中,pinpoing的探针对吞吐量的影响较为明显,在500并发用户时,测试服务的吞吐量从1385降低到774,影响很大。然后分析CPU和memory的影响,在内部服务进行的压测,对cpu和memory的影响都差不多在10%之内。
skywalking主要功能特征
1.多种监控手段,可以通过语言探针和service mesh获取监控的数据;
2.支持多种语言自动探针,包括java、.NET Core 和Node.js
3.轻量搞笑,无需大数据平台和大量的服务器资源
4.模块化,UI、存储、集群管理都有多种机制可选
5.支持告警
6.优秀的可视化解决方案
1、SkyWalking环境搭建部署
下载地址:https://skywalking.apache.org/downloads/
- skywalking agent和业务系统绑定在一起,负责收集各种监控数据
- skywalking oapservice是负责处理监控数据的,比如接受skywalking agent的监控数据,并存储在数据库中;接受skywalking webapp的前端请求,从数据库中查询数据,并返回数据给前端,skywalking oapservice通常已集群的形式存在。
- skywalking webapp,前端界面,用于展示数据
- 用于存储监控数据的数据库,比如mysql、elasticsearch
下载完成以后解压,双击bin/startup.bat 启动(该启动同时启动了oapservice和webappservice,所以后面就不用在此启动了)
1.1目录结构:
- webapp:UI前端(web监控页面)的jar包和配置文件
在该目录下的webapp.yml中可以修改ui的端口号
- oap-libs:后台应用的jar包,以及他的依赖jar包,里面有一个server-starter-*.jar就是启动程序
- config:启动后台应用程序的配置文件,是使用的各种配置
在该目录下的application.yml文件中进行修改存储方式,默认的是h2内存的方式
- bin:各种启动脚本,一般使用脚本startup.*来启动web页面和对应的后台应用
- oapService.*:默认使用的后台 程序的启动脚本 (使用的是默认模式启动,还支持各种模式,各模式区别见 启动模式)
- oapServiceInit.*:使用init模式启动;在此模式下,OAP服务器启动以执行初始化工作,然后退出
- oapServiceNoint.* 使用no init模式启动;在此模式下,OAP服务器不进行初始化
- webappService.* UI前端的启动脚本
- startup.* 组合脚本,同事启动oapService.*、 webappService.* 脚本
- agent(构建微服务时需要使用 )
- kywalking-agent.jar 代理服务jar包
- config 代理服务器启动时使用的配置文件
- plugins 包含多个插件 代理服务启动时会加载该目录下的所有的插件(实际是各种jar包)
- optional-plugins 可选插件,当需要支持某种功能时,比如 springcloud Gateway 则需要把对应的jar拷贝到plugins目录下
1.2搭建SkyWalking OAP服务
启动脚本bin/startup.sh(windows是以bat结尾的)
日志信息存储在logs目录
启动成功后悔启动两个服务,一个是skywalking-oap-server,一个是skywalking-web-ui
skywalking-oap-server服务启动后会暴露11800和12800两个端口,分别为手机监控数据的端口11800和接受前端请求的端口12800,修改端口可以修改config/application.yml
skywalking-web-ui服务会占用8080端口,修改端口可以修改web/webapp.yml
server.port:skywalking的服务端口 默认时8080
collector.ribbon.listOfServers:skywalking AOP服务地址数组,skywalking UI界面的数据是通过请求skywalking AOP服务来获得的。
1.3skywalking接入微服务
1.3.1 linux环境-通过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 SJAVA_AGENT=-javaagent:/usr/local/soft/apache-skywalking-apm-bin-es7/agent/skywalking-agent.jar
java $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 UI
agent.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参数配置方式优先级更高
1.3.2windows环境-在IDEA中使用skywalking
在运行的程序配置jvm参数,如下图所示:
#skywalking-agent.jar的本地磁盘的路径
-javaagent:E:\app\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar
#在skywalking上显示的服务名
-DSW_AGENT_NAME=springboot-skywalking-demo
#skywalking的collector服务的ip以及端口
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800
注意:-DSW_AGENT_COLLECTOR_BACKEND_SERVICES可以指定远程地址,但是-javaagent必须绑定本机的物理路径的skywalking-agent.jar
访问路由的地址,skywalking中可以看到添加的服务:
1.4skywalking跨多个微服务跟踪
skywalking跨多个微服务跟踪,只需要每个微服务启动时添加java agent参数即可。
测试:
启动微服务api-gateway,alibaba-order-seata,alibaba-stock-seata,配置skywalking的jvm参数
注意:此处存在bug,跟踪链路不显示gateway
拷贝agent/optional-plugins目录下的gateway插件到agent/plugins目录
重启skywalking和gateway的服务,即显示拓扑图的结构
1.5skywalking持久化跟踪数据
默认使用H2数据库存储
config/application.yml
1.5.1基于mysql持久化
1、修改config目录下的applicaiton.yml,使用mysql作为持久化存储的仓库
2.修改mysql连接配置
当前操作存在一个bug,启动的时候只启动了webapp 未启动oapservice,查看日志发现,没有mysql驱动导致的,所以要找一个mysql驱动放在aop-libs目录下重新启动aopservice即可。
注意:只需要建数据库即可 然后重新启动skywalking的时候会自动在相应的数据库中建表
---至此完成mysql的持久化--
1.6自定义skywalking链路追踪
如果我们希望对项目中的业务方法,实现链路追踪,方便我们排查问题,可以使用如下的代码
引入依赖:
<!--skywalking工具类-->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.5.0</version>
</dependency>
1.6.1@Trace将方法加入到追踪链路
如果一个业务方法想在ui界面的跟踪链路上显示出来,只需要在业务(impl中)方法上加上@Trace注解即可
@Override
@GlobalTransactional
@Trace
public String insertAlibabaOrder() {
Order order = new Order();
order.setId(UUID.randomUUID().toString());
order.setProductId("1");
order.setStatus("0");
order.setTotalAmount("100");
orderMapper.insertAlibabaOrder(order);
//减少库存
stockService.updateStock(order.getProductId());
//int i=1/0;
return "下单服务,添加订单,减少库存";
}
1.6.2加入@Tags或@Tag
我们还可以为追踪链路增加其他额外的信息,比如记录参数和返回信息。实现方式:在方法上增加@Tag或者@Tags
@Tag注解中
key=方法名(一般,也可修改),
value=returnedObj 返回值 arg[0]为参数 不可更改
@Override
@Trace
@Tag(key = "list",value = "returnedObj")
public List<Order> list() {
List<Order> orders = orderMapper.selectAll();
return orders;
}
@Override
@Trace
@Tags({@Tag(key = "param",value="arg[0]"),
@Tag(key = "order",value = "returnedObj") })
public Order getInfo(String id) {
Order order = orderMapper.selectinfoById(id);
return order;
}
访问接口以后在skywalking的显示结果为:
性能分析
skywalking的性能分析,在根据服务名称、端口名称,以及相应的规则建立了任务列表后,在调用了此任务列表的端口后。skywalking会自动记录,剖析当前端口,生成剖析结果,具体流程如图: