微服务链路追踪SkyWalking

Posted mry6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微服务链路追踪SkyWalking相关的知识,希望对你有一定的参考价值。

微服务链路追踪SkyWalking

链路追踪介绍

对于一个大型的几十个、几百个微服务构成的微服务架构系统,通常会遇到下面一些问题,比如:
(1) 如何串联整个调用链路,快速定位问题?
(2) 如何缕清各个微服务之间的依赖关系?
(3) 如何进行各个微服务接口的性能分析?
(4) 如何跟踪整个业务流程的调用处理顺序?

skywalking是什么

skywalking是一个国产开源框架,2015年由吴晟开源,2017年加入Apache孵化器。skywalking是分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计。它是一款优秀的APM(Application Performance Management)工具,包括了分布式追踪、性能指标分析、应用和服务依赖分析等。
官网:http://skywalking.apache.org/
下载:http://skywalking.apache.org/downloads/
Github:http://github.com/apache/skywalking
文档:http://skywalking.apache.org/docs/main/v8.4.0/readme/
中午文档:http://skyapm.github.io/document-cn-translation-of-skywalking/

1.链路追踪框架对比
(1) Zipkin是Twitter开源的调用链分析工具,目前基于springcloud sleuth得到了广泛的使用,特点是轻量,使用部署简单。
(2) Pinpoint是韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具,特点是支持多种插件,UI功能强大,接入端无代码侵入。
(3) SkyWalking是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具,特点是支持多种插件,UI功能较强,接入端无代码侵入。 目前已加入Apache孵化器。
(4) CAT是大众点评开源的基于编码和配置的调用链分析,应用监控分析,日志采集,监控报警等一系列的监控平台工具。

2.基本原理

项目CATZipkinSkyWalking
调用链可视化
聚合报表非常丰富较丰富
服务依赖图简单简单
埋点方式侵入式侵入式非侵入,字节码增强
VM监控指标
支持语言java/.net丰富java/.net/Nodejs/php/go
存储机制mysql(报表)、本地文件/HDFS(调用链)内存、es、mysql等H2、es
社区支持主要在国内国外主流Apache支持
使用案例美团、携程、陆金所京东、阿里定制后不开源华为、小米、当当、微众银行
APM
开发基础eBayGoogle DapperGoogle Dapper
是否支持webflux
Github stars(2019.12)12.3K12.2K11.8K

3.性能对比
模拟了三种并发用户: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%之内。

4.SkyWalking主要功能特性
(1) 多种监控手段,可以通过语言探针和service mesh获得监控的数据;
(2) 支持多种语言自动探针,包括Java、.Net Core 和 Node.js;
(3) 轻量高效,无需大数据平台和大量的服务器资源;
(4) 模块化。UI、存储、集群管理都有多种机制可选;
(5) 支持告警;
(6) 优秀的可视化解决方案;

SkyWalking环境搭建部署


(1) SkyWalking agent和业务系统绑定在一起,负责收集各种监控数据
(2) SkyWalking oapservice是负责处理监控数据的,比如接受SkyWalking agent的监控数据,并存储在数据库中;接受SkyWalking webapp的前端请求,从数据库查询数据,并返回数据给前端。SkyWalking oapservice通常以集群的形式存在。
(3) SkyWalking webapp,前端界面,用于展示数据。
(4) 用于存储监控数据的数据库,比如mysql、elasticsearch等。

1.下载SkyWalking
下载地址:http://skywalking.apache.org/downloads/

目录结构:

1》webapp:UI前端(web监控页面)的jar包和配置文件;
2》oap-libs:后台应用的jar包,以及它的依赖jar包,里边有一个server-starter-.jar就是启动程序;
3》config:启动后台应用程序的配置文件,是存放应用的各种配置
4》bin:各种启动脚本,一般使用脚本startup.来启动web页面和对应的后台应用;
(1) oapService.
:默认使用的后台程序的启动脚本;(使用的是默认模式启动,还支持其他模式,各模式区别见启动模式)
(2) oapServiceInit.
:使用init模式启动;在此模式下,OAP服务器启动以执行初始化工作,然后退出
(3) oapServiceNoInit.:使用no init模式启动;在此模式下,OAP服务器不进行初始化。
(4) webappService.
:UI前端的启动脚本;
(5) startup.:组合脚本,同时启动oapService.、webappService.*脚本;
5》agent
(1) skywalking-agent.jar:代理服务jar包
(2) config:代理服务启动时使用的配置文件
(3) plugins:包含多个插件,代理服务启动时会加载该目录下的所有插件(实际是各种jar包)
(4) optional-plugins:可选插件,当需要支持某种功能时,比如SpringCloud Gateway,则需要把对应的jar包拷贝到plugins目录下;

2.搭建SkyWalking OAP服务
1》启动脚本
bin/startup.sh

2》日志信息存储在logs目录

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

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

5》浏览web页面:http://localhost:8868/

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

3.SkyWalking中三个概念
服务(Service):表示对请求提供相同行为的一系列或一组工作负载,在使用Agent时,可以定义服务的名字;
服务实例(Service Instance):上述的一组工作负载中的每一个工作负载称为一个实例,一个服务实例实际就是操作系统上的一个真实进程;
端点(Endpoint):对于特定服务所接收的请求路径,如HTTP的URL路径和gRPC的服务的类名 + 方法签名;

SkyWalking跨多个微服务跟踪

SkyWalking跨多个微服务跟踪,只需要每个微服务启动时添加javaagent参数即可。
测试:
启动微服务api-gateway、alibaba-order-seata、alibaba-stock-seata,配置skywalking的jvm参数

-javaagent:D:\\server\\apache-skywalking-apm-bin-es7\\agent\\skywalking-agent.jar
-DSW_AGENT_NAME=alibaba-stock-seata
-DSW_AGENT_COLLECTOR_BACKEEND_SERVICES=127.0.0.1:11800

请求地址:http://localhost:8088/order/add

SkyWalking UI介绍

SkyWalking UI页面功能
1.菜单栏

仪表盘:查看被监控服务的运行状态;
拓扑图:以拓扑图的方式展现服务之间的关系,并以此为入口查看相关信息;
追踪:以接口列表的方式展现,追踪接口内部调用过程;
性能剖析:对端点进行采样分析,并可查看堆栈信息;
告警:触发告警的告警列表,包括服务失败率,请求超时等;
自动刷新:刷新当前页面数据内容;

2.控制栏

第一栏:不同内容主题的监控面板,应用性能管理/数据库/容器等;
第二栏:操作,包括编辑/导出当前数据/倒入展示数据/不同服务端点筛选展示;
第三栏:不同维度展示,全局/服务/实例/端点;

3.展示栏
Global全局维度
第一栏:Global、Service、Instance、Endpoint不同展示版面;
Service load:服务每分钟请求数;
Slow Service:慢响应服务,单位ms;
Un-Health Services(Apdex):Apdex性能指标,1为满分;
Slow Endpoint:慢响应端点,单位ms;
Global Response Latency:百分比响应延时,不同百分比的延时时间,单位ms;
Global Heatmap:服务响应时间热力分布图,根据时间段内不同响应时间的数量显示颜色深度;
底部栏:展示数据的时间区间,点击可以调整;

4.Service服务维度
Service Apdex(数字):当前服务的评分;
Service Apdex(折线图):不同时间的Apdex评分;
Service Avg Response Times:平均响应延时,单位ms;
Service Response Time Percentile:百分比响应延时;
Successful Rate(数字):请求成功率;
Successful Rate(折线图):不同时间的请求成功率;
Service Load(数字):每分钟请求数;
Service Load(折线图):不同时间的每分钟请求数;
Service Instances Load:每个服务实例的每分钟请求数;
Show Service Instance:每个服务实例的最大延时;
Service Instance Successful Rate:每个服务实例的请求成功率;

5.Instance服务维度
Service Instance Load:当前实例的每分钟请求数;
Service Instance Successful Rate:当前实例的请求成功率;
Service Instance Latency:当前实例的响应延时;
JVM CPU:jvm占用CPU的百分比;
JVM Memory:JVM内存占用大小,单位m;
JVM GC Time:JVM垃圾回收时间,包含YGC和OGC;
JVM GC Count:JVM垃圾回收次数,包含YGC和OGC;
JVM Thread Count:JVM线程数;
还有几个是.NET的,类似于JVM虚拟机,暂时不做说明;

6.Endpoint端点(API)维度
Endpoint Load in Current Service:每个端点的每分钟请求数;
Slow Endpoint in Current Service:每个端点的最慢请求时间,单位ms;
Successful Rate in Current Service:每个端点的请求成功率;
Endpoint Load:当前端点每个时间段的请求数据;
Endpoint Avg Response Time:当前端点每个时间段的请求行响应时间;
Endpoint Response Time Percentile:当前端点每个时间段的响应时间占比;
Endpoint Successful Rate:当前端点每个时间段的请求成功率;

7.拓扑图
1》选择不同的服务关联拓扑图;
2》查看单个服务相关内容;
3》服务间连接情况;
4》分组展示服务拓扑;

8.追踪
左侧:api接口列表,红色-异常请求,蓝色-正常请求;
右侧:api追踪列表,api请求连接各端点的先后顺序和时间;

SkyWalking接入微服务

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 JAVA_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.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参数配置方式优先级更高

2.Windows环境 – 在IDEA中使用SkyWalking
在运行的程序配置jvm参数;如下图所示:

# skywalking-agent.jar的本地磁盘的路径
-javaagent:D:\\server\\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

注意:此处存在bug,跟踪链路不显示gateway
拷贝agent/optional-plugins目录下的gateway插件到agent/plugins目录下

SkyWalking持久化跟踪数据

默认使用的H2数据库存储
config/application.yml


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

2》修改mysql连接配置

3》新建swtest数据库,swtest数据库中的表会在SkyWalking启动时自动生成

4》启动SkyWalking服务

启动时报下面异常:

原因:因为oap-libs中没有jdbc驱动jar包。
解决方法:在oap-libs文件夹中添加jdbc驱动jar包(mysql-connector-java-8.0.21.jar).

自定义SkyWalking链路追踪

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

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

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

@Override
@Trace
public List<Order> all() throws InterruptedException 
    TimeUnit.SECONDS.sleep(2);
    return orderMapper.selectAll();

测试:

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

@Service
public class OrderServiceImpl implements OrderService 

    @Autowired
    OrderMapper orderMapper;

    @Override
    @Trace
    @Tag(key = "getAll", value = "returnedObj")
    public List<Order> all() throws InterruptedException 
        TimeUnit.SECONDS.sleep(2);
        return orderMapper.selectAll();
    

    @Override
    @Trace
    @Tags(@Tag(key = "param", value = "arg[0]"),
            @Tag(key = "get", value = "returnedObj"))
    public Order get(Integer id) 
        return orderMapper.selectByPrimaryKey(id);
    

测试:

性能分析

SkyWalking的性能分析,在根据服务名称、端点名称,以及相应的规则建立了任务列表后,在调用了此任务列表的端点后。SkyWalking会自动记录,剖析当前端口,生成剖析结果,具体流程如图:

SkyWalking集成日志框架

logback官方配置

引入依赖

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

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

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 引入Spring Boot 默认的logback XML 配置文件-->
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!--日志的格式化-->
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <Pattern>-%clr(%d$LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS)faint %clr($LOG_LEVEL_PATTERN:-%5p) %clr($PID:- )magenta [%tid] %clr(---)faint %clr([%15.15t])faint %clr(%-40.40logger39)cyan %clr(:)faint %m%n$LOG_EXCEPTION_CONVERSION_WORD:-%wEx</Pattern>
            </layout>
        </encoder>
    </appender>

    <!-- 设置Appender-->
    <root level="INFO">
        <appender-ref ref="console"/>
    </root>
</configuration>


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">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
        <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
            <Pattern>%dyyyy-MM-dd HH:mm:ss.SSS [%Xtid] [%thread] %-5level %logger36 -%msg%n</Pattern>
        </layout>
    </encoder>
</appender>

<!-- 设置Appender-->
<root level="INFO">
    <appender-ref ref="console"/>
    <appender-ref ref="grpc-log"/>
</root>

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

plugin.toolkit.log.grpc.reporter.server_host=$SW_GRPC_LOG_SERVER_HOST:127.0.0.1
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在本地的可以不配

配置名解释默认值
plugin.toolkit.log.transmit_formatted是否以格式化或未格式化的格式传输记录的数据true
plugin.toolkit.log.grpc.reporter.server_host指定要向其报告日志数据的grpc服务器的主机127.0.0.1
plugin.toolkit.log.grpc.reporter.server_port指定要向其报告日志数据的grpc服务器的端口11800
plugin.toolkit.log.grpc.reporter.max_message_size指定grpc客户端要报告的日志数据的最大大小10485760
plugin.toolkit.log.grpc.reporter.upstream_timeout客户端向上游发送数据时将超时多长时间。单位是秒30

Skywalking UI效果:

SkyWalking告警功能

SkyWalking告警功能是在6.x版本新增的,其核心由一组规则驱动,这些规则定义在config/alarm-setting.yml文件中,告警规则的定义分为两部分:
1》告警规则:它们定义了应该如何触发度量警报,应该考虑什么条件。
2》Webhook(网络钩子):定义当警告触发时,哪些服务端需要被告知

1.告警规则
SkyWalking的发行版都会默认提供config/alarm-setting.yml文件,里面预先定义了一些常用的告警规则,如下:
1》过去3分钟内服务平均响应时间超过1秒。
2》过去2分钟服务成功率低于80%。
3》过去3分钟内服务响应时间超过1s的百分比。
4》服务实例在过去2分钟内平均响应时间超过1s,并且实例名称与正则表达式匹配。
5》过去2分钟内端点平均响应时间超过1秒。
6》过去2分钟内数据库访问平均响应时间超过1秒。
7》过去2分钟内端点关系平均响应时间超过1秒。
这些预定义的告警规则,打开config/alarm-setting.yml文件即可看到

告警规则配置项的说明:
1》Rule name:规则名称,也是在告警信息中显示的唯一名称,必须以_rule结尾,前缀可自定义
2》Metrics name:度量名称,取值为oal脚本中的度量名,目前只支持long、double和int类型。详见Official OAL script
3》Include names:该规则作用于哪些实体名称,比如服务名,终端名(可选,默认为全部)
4》Exclude names:该规则作不用于哪些实体名称,比如服务名,终端名(可选,默认为全部)
5》Threshold:阈值
6》OP:操作符,目前支持>,<,=
7》Period:多久警告规则需要被核实一下,这是一个时间窗口,与后端部署环境时间相匹配
8》Count:在一个Period窗口中,如果values超时Threshold值(按op),达到Count值,需要发送警报
9》Sitence period:在时间N中触发报警后,在TN -> TN + period这个阶段不告警。默认情况下,它和Period一样,这意味着看相同的告警(在同一个Metrics name拥有相同的id)在同一个Ponod内只会触发一次
10》message:告警信息

Webhook(网络钩子)
Webhook可以简单理解为是一种Web层面的回调机制,通常由一些事件触发,与代码中的事件回调类似,只不过是Web层面的。由于是Web层面的,所以当事件发生时,回调的不再是代码中的方法或函数,而是服务接口。例如,在警告这个场景,警告就是一个事件,当该事件发生时,SkyWalking就会主动去调用一个配置好的接口,该接口就是所谓的Webhook。
SkyWalking的告警消息会通过HTTP请求进行发送,请求方法为POST,Content-Type为application/json,其JSON数据是基于List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage>进行序列化的。JSON数据示例:

[
	"scopeId": 1, 
	"scope": "SERVICE",
	"name": "serviceA", 
	"id0": "12",  
	"id1": "",  
    "ruleName": "service_resp_time_rule",
	"alarmMessage": "alarmMessage xxxx",
	"startTime": 1560524171000
, 
	"scopeId": 1,
	"scope": "SERVICE",
	"name": "serviceB",
	"id0": "23",
	"id1": "",
    "ruleName": "service_resp_time_rule",
	"alarmMessage": "alarmMessage yyy",
	"startTime": 1560524171000
]

字段说明:
1》scopeld、scope:所有可用的Scope详见org.apache.skywalking.oap.server.core.source.DefaultScopeDefine
2》name:目标Scope的实体名称
3》Id0:Scope实体的ID
4》Id1:保留字段,目前暂未使用
5》ruleName:告警规则名称
6》alarmMessage:告警消息内容
7》startTime:告警时间,格式为时间戳

告警信息在项目日志中输出
1.在config/alarm-setting.yml中添加请求地址

2.SwAlarmDTO实体类

public class SwAlarmDTO 

    private int scopeId;
    private String scope;
    private String name;
    private String id0;
    private String id1;
    private String ruleName;
    private String alarmMessage;
    以上是关于微服务链路追踪SkyWalking的主要内容,如果未能解决你的问题,请参考以下文章

微服务链路追踪-SkyWalking

Spring Cloud Alibaba全家桶——微服务链路追踪SkyWalking

Kubernetes + Spring Cloud 集成链路追踪 SkyWalking

专为云原生微服务架构而设计的链路追踪工具 SkyWalking介绍及搭建

微服务的链路追踪和流量可视化-钉钉告警

Skywalking全链路监控集群和动态部署