WM_Skywalking应用实战 暂时没用

Skywalking应用实战
能力目标:
能够理解服务监控三要素
能够理解常用的
APM系统优势差异
能够基于
IDEA集成Skywalking Agent
能基于生产环境使用Skywalking Agent
掌握Rocketbot
性能分析
链路追踪
仪表盘应用
Webhook
1 Skywalking概述
随着互联网架构的扩张,分布式系统变得日趋复杂,越来越多的组件开始走向分布式化,如微服务、消
息收发、分布式数据库、分布式缓存、分布式对象存储、跨域调用,这些组件共同构成了繁杂的分布式
网络。
我们思考下这些问题:
这些问题要想得到解决,一定是有数据支撑,绝不是靠开发人员或者运维人员的直觉。为了解决分布式
应用、微服务系统面临的这些挑战,APM系统营运而生。
1:一个请求经过了这些服务后其中出现了一个调用失败的问题,如何定位问题发生的地方?
2:如何计算每个节点访问流量?
3:流量波动的时候,增加哪些节点集群服务?
 
 
1.1 微服务系统监控三要素
Logging 就是记录系统行为的离散事件,例如,服务在处理某个请求时打印的错误日志,我们可以
将这些日志信息记录到 ElasticSearch 或是其他存储中,然后通过 Kibana 或是其他工具来分析这
些日志了解服务的行为和状态。大多数情况下,日志记录的数据很分散,并且相互独立,比如错误
日志、请求处理过程中关键步骤的日志等等。
Metrics 是系统在一段时间内某一方面的某个度量,可聚合的数据,且通常是固定类型的时序数
据,例如,电商系统在一分钟内的请求次数。我们常见的监控系统中记录的数据都属于这个范畴,
例如 Promethus、Open-Falcon 等,这些监控系统最终给运维人员展示的是一张张二维的折线
图。Metrics 是可以聚合的,例如,为电商系统中每个 HTTP 接口添加一个计数器,计算每个接口
的 QPS,之后我们就可以通过简单的加和计算得到系统的总负载情况。
Tracing 即我们常说的分布式链路追踪,记录单个请求的处理流程,其中包括服务调用和处理时长
等信息。在微服务架构系统中一个请求会经过很多服务处理,调用链路会非常长,要确定中间哪个
服务出现异常是非常麻烦的一件事。通过分布式链路追踪,运维人员就可以构建一个请求的视图,
这个视图上展示了一个请求从进入系统开始到返回响应的整个流程。这样,就可以从中了解到所有
服务的异常情况、网络调用,以及系统的性能瓶颈等。
1.2 什么是链路追踪
谷歌在 2010 年 4 月发表了一篇论文《Dapper, a Large-Scale Distributed Systems Tracing
Infrastructure》介绍了分布式追踪的概念,之后很多互联网公司都开始根据这篇论文打造自己的分布式
链路追踪系统。APM 系统的核心技术就是分布式链路追踪。
论文在线地址:https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36356.pdf,
国内的翻译版:https://bigbully.github.io/Dapper-translation/
在此文中阐述了Google在生产环境下对于分布式链路追踪系统Drapper的设计思路与使用经验。随后各
大厂商基于这篇论文都开始自研自家的分布式链路追踪产品。如阿里的Eagle eye(鹰眼)、zipkin,京东
的“Hydra”、大众点评的“CAT”、新浪的“Watchman”、唯品会的“Microscope”、窝窝网的“Tracing”都是
基于这片文章的设计思路而实现的。所以要学习分布式链路追踪,对于Dapper论文的理解至关重要。
 
 
但是也带来了新的问题:各家的分布式追踪方案是互不兼容的,这才诞生了 OpenTracing。
OpenTracing 是一个 Library,定义了一套通用的数据上报接口,要求各个分布式追踪系统都来实现这
套接口。这样一来,应用程序只需要对接 OpenTracing,而无需关心后端采用的到底什么分布式追踪系
统,因此开发者可以无缝切换分布式追踪系统,也使得在通用代码库增加对分布式追踪的支持成为可
能。
OpenTracing 于 2016 年 10 月加入 CNCF(云原生计算基金会)基金会,是继 Kubernetes 和
Prometheus 之后,第三个加入CNCF 的开源项目。它是一个中立的(厂商无关、平台无关)分布式追
踪的 API 规范,提供统一接口,可方便开发者在自己的服务中集成一种或多种分布式追踪的实现。
OpenTracing API 目前支持的语言众多:
 
 
目前,主流的分布式追踪实现基本都已经支持 OpenTracing。
1.2.1 链路追踪
下面通过官方的一个示例简单介绍说明什么是 Tracing,把Tracing学完后,更有助于大家运用Skywalking
UI进行数据分析。
在一个分布式系统中,追踪一个事务或者调用流程,可以用下图方式描绘出来。这类流程图可以看清各
组件的组合关系,但它并不能看出一次调用触发了哪个组件调用、什么时间调用、是串行调用还是并行
调用。
一种更有效的展现方式就是下图这样,这是一个典型的 trace 视图,这种展现方式增加显示了执行时间
的上下文,相关服务间的层次关系,进程或者任务的串行或并行调用关系。这样的视图有助于发现系统
调用的关键路径。通过关注关键路径的执行过程,开发团队就可以专注于优化路径中的关键服务,最大
幅度的提升系统性能。例如下图中,我们可以看到请求串行的调用了授权服务、订单服务以及资源服
务,在资源服务中又并行的执行了三个子任务。我们还可以看到,在这整个请求的生命周期中,资源服
务耗时是最长的。
 
 
分布式追踪系统的原理:
分布式追踪系统大体分为三个部分,数据采集、数据持久化、数据展示。数据采集是指在代码中埋点,
设置请求中要上报的阶段,以及设置当前记录的阶段隶属于哪个上级阶段。数据持久化则是指将上报的
数据落盘存储,数据展示则是前端查询与之关联的请求阶段,并在界面上呈现。
上图是一个请求的流程例子,请求从客户端发出,到达负载均衡,再依次进行认证、计费,最后取到目
标资源。请求过程被采集之后,会以上图的形式呈现,横坐标是时间,圆角矩形是请求的执行的各个阶
1.2.2 OpenTracing
学好OpenTracing,更有助于我们运用Skywalking 。
1、数据模型:
这部分在 OpenTracing 的规范中写的非常清楚,下面只大概翻译一下其中的关键部分,细节可参考原始
文档 《The OpenTracing Semantic Specification》。
Causal relationships between Spans in a single Trace
解释了Trace 和 Span的因果关系
[Span A] ←←←(the root span)
|
+------+------+
| |
[Span B] [Span C] ←←←(Span C is a `ChildOf` Span A)
| |
[Span D] +---+-------+
| |
[Span E] [Span F] >>> [Span G] >>> [Span H]
(Span G `FollowsFrom` Span F)
 
 
Trace
一个 Trace 代表一个事务、请求或是流程在分布式系统中的执行过程。OpenTracing 中的一条 Trace调
用链,由多个 Span 组成,一个 Span 代表系统中具有开始时间和执行时长的逻辑单元,Span 一般会有
一个名称,一条 Trace 中 Span 是首尾连接的。
Span
Span 代表系统中具有开始时间和执行时长的逻辑单元,Span 之间通过嵌套或者顺序排列建立逻辑因果
关系。
如果按时间关系呈现的话如下所示:
每个 Span 中可以包含以下的信息:
操作名称:例如访问的具体 RPC 服务,访问的 URL 地址等;
起始时间;2021-1-25 22:00:00
结束时间;2021-1-30 22:00:00
Span Tag:一组键值对(k-v)构成的Span标签集合,其中键必须为字符串类型,值可以是字符
串、bool 值或者数字;
Span Log:一组 Span 的日志集合;
SpanContext:Trace 的全局上下文信息;
References:Span 之间的引用关系,下面详细说明 Span 之间的引用关系;
在一个 Trace 中,一个 Span 可以和一个或者多个 Span 间存在因果关系。目前,OpenTracing 定义了
ChildOf 和 FollowsFrom 两种 Span 之间的引用关系。这两种引用类型代表了子节点和父节点间的直接
因果关系。
ChildOf 关系:一个 Span 可能是一个父级 Span 的孩子,即为 ChildOf 关系。下面这些情况会构
成 ChildOf 关系:
一个 HTTP 请求之中,被调用的服务端产生的 Span,与发起调用的客户端产生的 Span,就
构成了 ChildOf 关系;
一个 SQL Insert 操作的 Span,和 ORM 的 save 方法的 Span 构成 ChildOf 关系。
很明显,上述 ChildOf 关系中的父级 Span 都要等待子 Span 的返回,子 Span 的执行时间影响了其所在
父级 Span 的执行时间,父级 Span 依赖子 Span 的执行结果。除了串行的任务之外,我们的逻辑中还有
很多并行的任务,它们对应的 Span 也是并行的,这种情况下一个父级 Span 可以合并所有子 Span 的执
行结果并等待所有并行子 Span 结束。
FollowsFrom 关系:表示跟随关系,意为在某个阶段之后发生了另一个阶段,用来描述顺序执行关系
Logs
每个 Span 可以进行多次 Logs 操作,每一次 Logs 操作,都需要带一个时间戳,以及一个可选的附加信
息。
Tags
––|–––––––
|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time
[Span A
···················································]
[Span B··············································]
[Span D··········································]
[Span C········································]
[Span E·······] [Span F··] [Span G··] [Span H··]
 
 
每个 Span 可以有多个键值对形式的 Tags,Tags 是没有时间戳的,只是为 Span 添加一些简单解释和补
充信息。
SpanContext 和 Baggage
SpanContext 表示进程边界,在跨进调用时需要将一些全局信息,例如,TraceId、当前 SpanId 等信息
封装到 Baggage 中传递到另一个进程(下游系统)中。
Baggage 是存储在 SpanContext 中的一个键值对集合。它会在一条 Trace 中全局传输,该 Trace 中的
所有 Span 都可以获取到其中的信息。
需要注意的是,由于 Baggage 需要跨进程全局传输,就会涉及相关数据的序列化和反序列化操作,如果
在 Baggage 中存放过多的数据,就会导致序列化和反序列化操作耗时变长,使整个系统的
RPC 的延迟
增加、吞吐量下降。
虽然 Baggage
与 Span Tags 一样,都是键值对集合,但两者最大区别在于 Span Tags 中的信息不会跨
进程传输,而 Baggage 需要全局传输。因此,OpenTracing 要求实现提供 Inject 和 Extract 两种操作,
SpanContext 可以通过 Inject 操作向 Baggage 中添加键值对数据,通过 Extract 从 Baggage 中获取键
值对数据。
2、核心接口语义
OpenTracing 希望各个实现平台能够根据上述的核心概念来建模实现,不仅如此,OpenTracing 还提供
了核心接口的描述,帮助开发人员更好的实现 OpenTracing 规范。
Span 接口
Span接口必须实现以下的功能:
获取关联的 SpanContext:通过 Span 获取关联的 SpanContext 对象。
关闭(Finish)Span:完成已经开始的 Span。
添加 Span Tag:为 Span 添加 Tag 键值对。
添加 Log:为 Span 增加一个 Log 事件。
添加 Baggage Item:向 Baggage 中添加一组键值对。
获取 Baggage Item:根据 Key 获取 Baggage 中的元素。
SpanContext 接口
SpanContext 接口必须实现以下功能,用户可以通过 Span 实例或者 Tracer 的 Extract 能力获取
SpanContext 接口实例。
Tracer 接口
Tracer 接口必须实现以下功能:
创建 Span:创建新的 Span。
注入 SpanContext:主要是将跨进程调用携带的 Baggage 数据记录到当前 SpanContext 中。
提取 SpanContext ,主要是将当前 SpanContext 中的全局信息提取出来,封装成 Baggage 用于
后续的跨进程调用。
 
 
1.3 常见APM系统
我们前面提到了APM系统,APM 系统(Application Performance Management,即应用性能管理)是
对企业的应用系统进行实时监控,实现对应用性能管理和故障定位的系统化解决方案,在运维中常用。
CAT(开源): 由国内美团点评开源的,基于 Java 语言开发,目前提供 Java、C/C++、Node.js、
Python、Go 等语言的客户端,监控数据会全量统计。国内很多公司在用,例如美团点评、携程、
拼多多等。CAT 需要开发人员手动在应用程序中埋点,对代码侵入性比较强。
Zipkin(开源):
由 Twitter 公司开发并开源,Java 语言实现。侵入性相对于
CAT
要低一点,需
要对web.xml
等相关配置文件进行修改,但依然对系统有一定的侵入性。
Zipkin
可以轻松与
Spring Cloud
进行集成,也是
Spring Cloud
推荐的 APM 系统。
Pinpoint
(开源):
韩国团队开源的
APM 产品,运用了字节码增强技术,只需要在启动时添加启
动参数即可实现 APM 功能,对代码无侵入。目前支持 Java 和 PHP 语言,底层采用 HBase 来存储
数据,探针收集的数据粒度非常细,但性能损耗较大,因其出现的时间较长,完成度也很高,文档
也较为丰富,应用的公司较多。
SkyWalking(开源): 国人开源的产品,2019 年 4 月 17 日 SkyWalking 从 Apache 基金会的孵
化器毕业成为顶级项目。目前 SkyWalking 支持 Java、.Net、Node.js 等探针,数据存储支持
MySQL、ElasticSearch等。
还有很多不开源的 APM 系统,例如,淘宝鹰眼、Google Dapper 等等。
我们将学习Skywalking,Skywalking有很多优秀特性。SkyWalking 对业务代码无侵入,性能表现优
秀,SkyWalking 增长势头强劲,社区活跃,中文文档齐全,支持多语言探针, SkyWalking 支持
Dubbo、gRPC、SOFARPC 等很多框架。
1.4 Skywalking介绍
2015年由个人吴晟(华为开发者)主导开源,作者是华为开发云监控产品经理,主导监控产品的规划、
技术路线及相关研发工作,也是OpenTracing分布式追踪标准组织成员 ,该项目 2017年加入Apache孵
化器,是一个分布式系统的应用程序性能监控工具(APM),专为微服务、云原生架构和基于容器
(Docker、K8s、Mesos)架构而设计。
官方站点:http://skywalking.apache.org/
GitHub项目地址:https://github.com/apache/skywalking
Skywalking是一个可观测性分析平台和应用性能管理系统,它也是基于OpenTracing规范、开源的AMP
系统。Skywalking提供分布式跟踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。支持
Java, .Net Core, PHP, NodeJS, Golang, LUA, c++代理。支持Istio 服务网格
我们在学习Skywalking之前,可以先访问官方提供的控制台演示
演示地址:http://demo.skywalking.apache.org/ 账号:skywalking 密码:skywalking
 
 
1、SkyWalking 核心功能:
指标分析:服务,实例,端点指标分析
问题分析:在运行时分析代码,找到问题的根本原因
服务拓扑:提供服务的拓扑图分析
依赖分析:服务实例和端点依赖性分析
服务检测:检测慢速的服务和端点
性能优化:根据服务监控的结果提供性能优化的思路
链路追踪:分布式跟踪和上下文传播
数据库监控:数据库访问指标监控统计,检测慢速数据库访问语句(包括SQL语句)
服务告警:服务告警功能
名词解释:
服务(service):业务资源应用系统
端点(endpoint):应用系统对外暴露的功能接口
实例(instance):物理机
 
 
2、SkyWalking 特点:
多语言自动探针,支持 Java、.NET Code 等多种语言。
为多种开源项目提供了插件,为 Tomcat、 HttpClient、Spring、RabbitMQ、MySQL 等常见基础
设施和组件提供了自动探针。
微内核 + 插件的架构,存储、集群管理、使用插件集合都可以进行自由选择。
支持告警。
优秀的可视化效果。
3、Skywalking
架构图:
skyWalking整体可分为:客户端,服务端
客户端:agent组件
基于探针技术采集服务相关信息(包括跟踪数据和统计数据),然后将采集到的数据上报给
skywalking的数据收集器
服务端:又分为OAP,Storage,WebUI
OAP:observability analysis platform可观测性分析平台,负责接收客户端上报的数据,对数据
进行分析,聚合,计算后将数据进行存储,并且还会提供一些查询API进行数据的查询,这个模块
其实就是我们所说的链路追踪系统的Collector收集器
Storage:skyWalking的存储介质,默认是采用H2,同时支持许多其他的存储介质,比如:
ElastaticSearch,mysql等
WebUI:提供一些图形化界面展示对应的跟踪数据,指标数据等等
2 Skywalking安装
Skywalking数据存储方式有2种,分别为H2(内存)和elasticsearch,如果数据量比较大,建议使用后者,
工作中也建议使用后者。
Skywalking自身提供了UI管理控制台,我们安装的组件:
 
 
2.1 elasticsearch安装
1)系统资源配置修改
elasticsearch
占用系统资源比较大,我们需要修改下系统资源配置,这样才能很好的运行
elasticsearch,修改虚拟机配置, vi /etc/security/limits.conf ,追加内容:
修改 vi /etc/sysctl.conf ,追加内容 :
让配置立即生效:
2)安装elasticsearch
建议安装:elasticsearch7.x,我们这里选择7.6.2,并且采用容器的安装方式,安装如下:
3)elasticsearch跨域配置
elasticsearch默认是没有开启跨域,我们需要配置跨域,并配置集群节点名字:
修改容器中 /usr/share/elasticsearch/config/elasticsearch.yml 文件,添加配置如下:
参数说明:
1:elasticsearch,建议使用elasticsearch7.x
2:elasticsearch-hq,elasticsearch的管理工具,更方便管理elasticsearch
3:Skywalking
4:Skywalking-UI
* soft nofile 65536
* hard nofile 65536
vm.max_map_count=655360
/sbin/sysctl -p
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 --restart=always -e
"discovery.type=single-node" -e ES_JAVA_OPTS="-Xms84m -Xmx512m" -d
elasticsearch:7.6.2
#进入容器
docker exec -it elasticsearch /bin/bash
cluster.name: "elasticsearch"
http.cors.enabled: true
http.cors.allow-origin: "*"
network.host: 0.0.0.0
discovery.zen.minimum_master_nodes: 1
 
 
安装完成后,重启容器
docker restart elasticsearch ,再访问 http://192.168.200.129:9200/
效果如下:
安装 ElasticSearch管理界面elasticsearch-hq
安装完成后,访问控制台地址 http://192.168.200.129:5000/#!/clusters/elasticsearch
cluster.name:集群服务名字
http.cors.enabled:开启跨域
http.cors.allow-origin: 允许跨域域名,*代表所有域名
network.host: 外部访问的IP
discovery.zen.minimum_master_nodes: 最小主节点个数
docker run -d --name elastic-hq -p 5000:5000 --restart always
elastichq/elasticsearch-hq
 
 
2.2 Skywalking安装
Skywalking的安装我们也采用Docker安装方式,同时我们需要为Skywalking指定存储服务:
参数说明:
接下来安装Skywalking-UI,需要指定Skywalking服务名字:
安装完成后,我们接下来访问Skywalking控制台:http://192.168.200.129:8080
关于SkywalkingUI的使用,我们在下一节知识点详细讲解。
2.3 Skywalking生产环境问题
1)ES分片数量上限
如果此时访问http://192.168.200.129:8080/ 出现500错误,错误如下,此时其实是Elasticsearch出了问
题:
我们可以查看 skywalking 的日志 docker logs --since 30m skywalking ,会报如下错误:
#安装Skywalking
docker run --name skywalking -d -p 1234:1234 -p 11800:11800 -p 12800:12800 --
restart always --link elasticsearch:elasticsearch -e SW_STORAGE=elasticsearch7 -
e SW_STORAGE_ES_CLUSTER_NODES=elasticsearch:9200 apache/skywalking-oap-server
--link ela
sticsearch:elasticsearch:存储服务使用elasticsearch
-e SW_STO
R
A
G
E
=e
l
a
st
ic
se
a
r
c
h
7
e
l
a
s
t
i
c
s
e
a
r
c
h
-e SW_STO
R
A
G
E_
ES
_
C
LU
ST
E
R_
N
O
D
E
S
=e
l
as
ti
c
s
e
a
r
c
h
:
9
2
0
0
:
服务elasticsearch的链接地址
docker run --name skywalking-ui -d -p 8080:8080 --link skywalking:skywalking -e
SW_OAP_ADDRESS=skywalking:12800 --restart always apache/skywalking-ui
"com.netflix.zuul.exception.ZuulException","message":"GENERAL"
 
 
这种错误一般是生产环境中Elasticsearch分片数量达到了峰值,es集群的默认最大分片数是1000,我们
需要调整Elasticsearch的默认分片数量,修改方式有多种,最常用的是直接修改 elasticsearch.yml
配置文件:
保存配置后,记得删除 data/nodes 数据包,再重启elasticsearch,此时就可以正常访问了。
2)磁盘清理
如果此时能打开 skywalking-ui 界面,但是没有数据,则需要清理磁盘空间,可能是磁盘空间满了,如
果是docker容器,可以使用 docker system prune 命令实现清理, docker system prune 命令可以
用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及dangling镜像(即无tag的镜像)。
docker system prune -a 命令清理得更加彻底,可以将没有容器使用Docker镜像都删掉。
2.4 docker-compose部署
创建 docker-compose.yml 并配置如下
Failed: 1: this action would add [2] total shards, but this cluster currently
has [1000]/[1000] maximum shards open;]
#进入elasticse
a
r
c
h
docker exec -
i
t
e
l
a
sticsearch /bin/bash
#编辑
vi /usr/sh
are/elasticsearch/config/elasticsearch.yml
#添加如下配置
cluster.m
ax_shards_per_node: 10000000
version: '3.3'
services:
elasticsearch:
image: elasticsearch:7.6.2
container_name: elasticsearch
restart: always
privileged: true
hostname: elasticsearch
ports:
- 9200:9200
- 9300:9300
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- TZ=Asia/Shanghai
networks:
- skywalking
ulimits:
memlock:
soft: -1
hard: -1
elasticsearch-hq:
image: elastichq/elasticsearch-hq
container_name: elasticsearch-hq
 
 
通过命令一键启动:
启动成功后访问skywalking的webui页面:http://192.168.200.129:8080/
restart: always
privileged: true
hostname: elasticsearch-hq
ports:
- 5000:5000
environment:
- TZ=Asia/Shanghai
networks:
- skywalking
oap:
image: ap
ache/skywalking-oap-server:8.3.0-es7
contai
ne
r
_
n
am
e: oap
hostna
m
e
:
o
a
p
privi
le
g
ed
:
true
depen
d
s_
o
n
:
- elasticsearch
links:
- elasticsearch
restart: always
ports:
- 11800:11800
- 12800:12800
environment:
SW_STORAGE: elasticsearch7
SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
TZ: Asia/Shanghai
volumes:
- ./config/alarm-settings.yml:/skywalking/config/alarm-settings.yml
networks:
- skywalking
ui:
image: apache/skywalking-ui:8.3.0
container_name: ui
privileged: true
depends_on:
- oap
links:
- oap
restart: always
ports:
- 8080:8080
environment:
SW_OAP_ADDRESS: oap:12800
TZ: Asia/Shanghai
networks:
- skywalking
networks:
skywalking:
driver: bridge
docker-compose up -d
 
 
3 Skywalking应用
相关术语:
3.1 agent
下载
Skywalking-agent
,它简称探针,用来收集和发送数据到归集器,我们先来学习下探针使用,探针对应
的jar包在Skywalking源码中,我们需要先下载源码。
Skywalking源码下载地址: https://archive.apache.org/dist/skywalking/ ,我们当前使用的版本是
8.3.0 ,选择下载对应版本。
agent目录结构如下:
目录结构说明:
skywalking-collector:链路数据归集器,数据可以落地ElasticSearch/H2
skywalking-ui:web可视化平台,用来展示落地的数据
skywalking-ag
ent:探针,用来收集和发送数据到归集器
agent
├── activations
│ ├── apm-toolkit-kafka-activation-8.3.0.jar
│ ├── ...
│ └── apm-toolkit-trace-activation-8.3.0.jar
├── config # Agent 配置文件
│ └── agent.config
├── logs # 日志文件
├── optional-plugins # 可选插件
│ ├── apm-customize-enhance-plugin-8.3.0.jar
│ ├── apm-gson-2.x-plugin-8.3.0.jar
│ └── ... ...
├── bootstrap-plugins # jdk插件
│ ├── apm-jdk-http-plugin-8.3.0.jar
│ └── apm-jdk-threading-plugin-8.3.0.jar
├── plugins # 当前生效插件
│ ├── apm-activemq-5.x-plugin-8.3.0.jar
│ ├── apm-armeria-0.84.x-plugin-8.3.0.jar
│ ├── apm-armeria-0.85.x-plugin-8.3.0.jar
│ └── ... ...
├── optional-reporter-plugins
│ └── kafka-reporter-plugin-8.3.0.jar
└── skywalking-agent.jar【应用的jar包】
 
 
我们在使用Skywalking的时候,整个过程中都会用到 skywalking-agent.jar ,而无论是RPC还是HTTP
开发的项目,用法都一样,因此我们讲解当前主流的
SpringBoot项目对agent的使用即可。
3.2 agent应用
项目使用agent,如果是开发环境,可以使用IDEA集成,如果是生产环境,需要将项目打包上传到服务
器。为了使用agent,我们同时需要将下载的 apache-skywalking-apm-bin 文件包上传到服务器上去。
不过无论是开发环境还是生产环境使用agent,对项目都是无侵入式的。
3.2.1 应用名配置
我们需要用到 agent ,此时需要将 agent/config/agent.config 配置文件拷贝到每个需要集成
Skywalking工程的resource目录下,我们将 agent.config 拷贝到 工程\hailtaxi-parent 的每个子工
程目录下,并修改其中的 agent.service_name,修改如下:
agent.config 是一个 KV 结构的配置文件,类似于 properties 文件,value 部分使用 "${}" 包裹,
其中使用冒号 (":") 分为两部分,前半部分是可以覆盖该配置项的系统环境变量名称,后半部分为默
认值。例如这里的 agent.service_name 配置项,如果系统环境变量中指定了 SW_AGENT_NAME 值(注
意,全是大写),则优先使用环境变量中指定的值,如果环境变量未指定,则使用 hailtaxi-driver
这个默认值。
直接把配置修改好后放到项目的resource目录下(或者其他路径)是最不容易才出错的一种方式,同时我
们可以采用其他方式覆盖默认值:
1)JVM覆盖配置
例如这里的 agent.service_name 配置项,如果在 JVM 启动之前,明确中指定了下面的 JVM 配置:
2)探针配置覆盖
activations 当前skywalking正在使用的功能组件。
agent.config 文件是 SkyWalking Agent 的唯一配置文件。
plugins 目录存储了当前 Agent 生效的插件。
optional-plugins 目录存储了一些可选的插件(这些插件可能会影响整个系统的性能或是有版权问题),
如果需要使用这些插件,需将相应 jar 包移动到 plugins 目录下。
skywalking-ag
ent.jar 是 Agent 的核心 jar 包,由它负责读取 agent.config 配置文件,加载上
述插件 jar 包,运行时收集到 的 Trace 和 Metrics 数据也是由它发送到 OAP 集群的。
hailtaxi-driver: agent.service_name=${SW_AGENT_NAME:hailtaxi-driver}
hailtaxi-order: agent.service_name=${SW_AGENT_NAME:hailtaxi-order}
# "skywalking."是 Skywalking环境变量的默认前缀
-Dskywalking.agent.service_name = hailtaxi-driver
 
 
将 Java Agent 配置为如下:
此时会使用该 Java Agent 配置值覆盖 agent.config 配置文件中 agent.service_name 默认值。
但是这些配置都有不同优先级,优先级如下:
3.2.2 IDEA
集成使用agent
1、修改agent中数据收集服务的地址: agent/config/agent.confg
当然也可以同构JVM参数配置
2、使用探针配置为2个项目分别配置agent:
1)hailtaxi-driver:
将上面配置赋值到IDEA中:
2)hailtaxi-order
# 默认格式是 -javaagent:agent.jar=[option1]=[value1],[option2]=[value2]
-javaagent:/path/skywalking-agent.jar=agent.service_name=hailtaxi-driver
探针配置 > JVM配
置 > 系统环境变量配置 > agent.config文件默认值
collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:192.168.200.129:
11800}
-javaagent:C:\developer\skywalking\apache-skywalking-apm-bin\agent\skywalking
agent.jar
-Dskywalking.agent.service_name=hailtaxi-driver
 
 
-javaagent:C:\developer\skywalking\apache-skywalking-apm-bin\agent\skywalking
agent.jar
-Dskywalking.agent.service_name=hailtaxi-order
将上面配置赋值到IDEA中:
 
 
 
此时启动IDEA,并访问:http://192.168.200.129:8080 效果如下:
如果你要追踪Gateway的话,你会发现:无法通过gateway发现路由的服务链路?
原因: Spring Cloud Gateway 是基于 WebFlux 实现,必须搭配上apm-spring-cloud-gateway-2.1.x
plugin 和 apm-spring-webflux-x.x-plugin 两个插件
方案:将agent/optional-plugins下的两个插件 复制到 agent/plugins目录下3.3.3 生产环境使用agent
生产环境使用,因此我们需要将agent和每个项目的jar包上传到服务器上,上传 apache-skywalking
apm-bin 至 /usr/local/server/skywalking ,再将 工程\hailtaxi-parent 中的项目打包,并分别上
传到服务器上
1)启动hailtaxi-driver
2)启动hailtaxi-order
3.3 Rocketbot
前面我们已经完成了SkyWalking环境搭建和项目应用agent使用,我们来看如何使用 SkyWalking 提供
的 UI 界面—— Skywalking Rocketbot。
OAP服务和Rocket(其实就是个web项目)均已启动
3.3.1 Rocketbot-仪表盘
具体细则可参考资料: Skywalking仪表盘使用
hailtaxi-order-1.0-SNAPSHOT.jar
hailtaxi-driver-1.0-SNAPSHOT.jar
java -jav
aagent:/usr/local/server/skywalking/apache-skywalking-apm
bin/agent/skywalking-agent.jar -Dskywalking.agent.service_name=hailtaxi-driver -
jar hailtaxi-driver-1.0-SNAPSHOT.jar &
java -javaagent:/usr/local/server/skywalking/apache-skywalking-apm
bin/agent/skywalking-agent.jar -Dskywalking.agent.service_name=hailtaxi-order -
jar hailtaxi-order-1.0-SNAPSHOT.jar &
 
 
Rocketbot从多个方面展示了服务信息,我们分别从多个方面进行讲解。
上图中的【仪表盘】、【拓扑图】、【追踪】、【性能剖析】、【日志】、【警告】属于功能菜单。
仪表盘属于数据统计功能,分别从服务热度、响应水平、服务个数、节点信息等展示统计数据。
Global Heatmap 面板:热力图,从全局展示了某段时间请求的热度。
Global Percent Response 面板 :展示了全局请求响应时间的 P99、P95、P75 等分位数。
Global Brief 面板:展示了 SkyWalking 能感知到的 Service、Endpoint 的个数。
Global Top Troughput 面板:展示了吞吐量前几名的服务。
Global Top Slow Endpoint 面板:展示了耗时前几名的 Endpoint。
Service (Avg) ResponseTime 面板:展示了指定服务的(平均)耗时。
Service (Avg) Throughput 面板:展示了指定服务的(平均)吞吐量。
Service (Avg) SLA 面板:展示了指定服务的(平均)SLA(Service Level Agreement,服务等级
协议)。
Service Percent Response 面板:展示了指定服务响应时间的分位数。
Service Slow Endpoint 面板:展示了指定服务中耗时比较长的 Endpoint 信息。
Running ServiceInstance 面板:展示了指定服务下的实例信息。
除了 SkyWalking Rocketbot 默认提供的这些面板,我们还可以点击锁型按钮,自定义 Global 面板。在
ServiceInstance 面板中展示了很多 ServiceInstance 相关的监控信息,例如,JVM 内存使用情况、GC
次数、GC 耗时、CPU 使用率、ServiceInstance SLA 等等信息。
3.3.2 Rocketbot-拓扑图
 
 
【拓扑图】展示当前整个业务服务的拓扑图。点击拓扑图中的任意节点,可以看到服务相应的状态信
息,其中包括响应的平均耗时、SLA 等监控信息。点击拓扑图中任意一条边,还可以看到一条调用链路
的监控信息,其中会分别从客户端(上游调用方)和服务端(下游接收方)来观测这条调用链路的状
态,其中展示了该条链路的耗时、吞吐量、SLA 等信息。
3.3.3 追踪
【追踪】主要用来查询 Trace 信息,如下图所示。在①处可以选择 Trace 的查询条件,其中可以指定
Trace 涉及到的 Service、ServiceInstance、Endpoint 以及Trace 的状态继续模糊查询,还可以指定
TraceId 和时间范围进行精确查询。在②处可以直接根据请求连接查找调用链路信息。在③处展示了
Trace 的简略信息。在④处可以选择不同的方式展示追踪信息。
在这里,我们不仅能看到调用链路信息,还能看到MySQL操作监控,如下图:
错误异常信息也能追踪,如下图:
 
 
3.3.4 性能分析
在传统的监控系统中,我们如果想要得知系统中的业务是否正常,会采用进程监控、日志收集分析
等方式来对系统进行监控。当机器或者服务出现问题时,则会触发告警及时通知负责人。通过这种方
式,我们可以得知具体哪些服务出现了问题。但是这时我们并不能得知具体的错误原因出在了哪里,开
发人员或者运维人员需要到日志系统里面查看错误日志,甚至需要到真实的业务服务器上查看执行情况
来解决问题。
如此一来,仅仅是发现问题的阶段,可能就会耗费相当长的时间;另外,发现问题但是并不能追溯
到问题产生具体原因的情况,也常有发生。这样反反复复极其耗费时间和精力,为此我们便有了基于分
布式追踪的APM系统。
通过将业务系统接入分布式追踪中,我们就像是给程序增加了一个放大镜功能,可以清晰看到真实
业务请求的整体链路,包括请求时间、请求路径,甚至是操作数据库的语句都可以看得一清二楚。通过
这种方式,我们结合告警便可以快速追踪到真实用户请求的完整链路信息,并且这些数据信息完全是持
久化的,可以随时进行查询,复盘错误的原因。
然而随着我们对服务监控理解的加深,我们发现事情并没有那么简单。在分布式链路追踪中我们有这样
的两个流派:代码埋点和字节码增强。无论使用哪种方式,底层逻辑一定都逃不过面向切面这个基础逻
辑。因为只有这样才可以做到大面积的使用。这也就决定了它只能做到框架级别和RPC粒度的监控。这
时我们可能依旧会遇到程序执行缓慢或者响应时间不稳定等情况,但无法具体查询到原因。这时候,大
家很自然的会考虑到增加埋点粒度,比如对所有的Spring Bean方法、甚至主要的业务层方法都加上埋
点。但是这种思路会遇到不小的挑战:
第一,增加埋点时系统开销大,埋点覆盖不够全面。通过这种方式我们确实可以做到具体业务场景具体
分析。但随着业务不断迭代上线,弊端也很明显:大量的埋点无疑会加大系统资源的开销,造成CPU、
内存使用率增加,更有可能拖慢整个链路的执行效率。虽然每个埋点消耗的性能很小,在微秒级别,但
是因为数量的增加,甚至因为业务代码重用造成重复埋点或者循环使用,此时的性能开销已经无法忽
略。
第二,动态埋点作为一项埋点技术,和手动埋点的性能消耗上十分类似,只是减少的代码修改量,但是
因为通用技术的特别,上一个挑战中提到的循环埋点和重复使用的场景甚至更为严重。比如选择所有方
法或者特定包下的所有方法埋点,很可能造成系统性能彻底崩溃。
第三,即使我们通过合理设计和埋点,解决了上述问题,但是JDK函数是广泛使用的,我们很难限制对
JDK API的使用场景。对JDK过多方法、特别是非RPC方法的监控会造成系统的巨大延迟风险。而且有一
些基础类型和底层工具类,是很难通过字节码进行增强的。当我们的SDK使用不当或者出现bug时,我
们无法具体得知真实的错误原因。
 
 
Skywalking中可以使用性能剖析分析特定端点的性能,我们需要先创建一个监控任务:
新建任务后,在右侧可以查看任务性能分析报表,还可以点击分析线程栈信息,如下图:
3.3.5 告警
SkyWalking 告警功能是在6.x版本新增的,其核心由一组规则驱动,这些规则定义在 config/alarm
settings.yml 文件中。 告警的定义分为两部分:
1. 告警规则:它们定义了应该如何触发度量警报,应该考虑什么条件。
2. Webhook(网络钩子):定义当警告触发时,哪些服务终端需要被告知
3.3.5.1 警告规则详解
Skywalking每隔一段时间根据收集到的链路追踪的数据和配置的告警规则(如服务响应时间、服务响应
时间百分比)等,判断如果达到阈值则发送相应的告警信息。发送告警信息是通过调用webhook接口完
成,具体的webhook接口可以使用者自行定义,从而开发者可以在指定的webhook接口中编写各种告警
方式,比如邮件、短信等。告警的信息也可以在RocketBot中查看到。
我们可以进入到Skywalking容器中,再进入到config文件夹下就可以看到alarm-settings.yml,如下图:
 
 
SkyWalking 的发行版都会默认提供 config/alarm-settings.yml 文件,里面预先定义了一些常用的告
警规则。如下:
# Licensed to
t
he
A
pa
c
he
So
f
t
wa
re
F
o
un
d
a
t
i
o
n
(
A
S
F
)
u
n
de
r
o
ne
# or more cont
ri
b
u
to
r
l
i
ce
n
s
e
ag
r
ee
m
e
n
t
s
.
S
ee
t
h
e
N
O
T
IC
E
f
ile
# distribu
t
ed
w
it
h
t
h
i
s
w
o
r
k
f
o
r
a
dd
i
t
io
n
al
i
nf
o
rm
at
i
o
n
# regardin
g
c
o
py
ri
g
ht
o
w
n
e
rs
h
i
p
.
T
he
A
S
F
l
ic
e
n
se
s
t
h
i
s file
# to you under the Apache License, Version 2.0 (the
# "Licens
e
")
;
y
o
u
m
a
y
no
t
u
s
e
t
h
i
s
f
i
le
e
x
c
e
p
t
i
n
c
o
m
pl
i
a
n
c
e
# with th
e
Li
c
e
n
s
e
.
Yo
u
ma
y
o
bt
a
i
n
a
c
o
py
o
f
t
he
L
i
ce
n
s
e
a
t
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Sample alarm rules.
rules:
# Rule unique name, must be ended with `_rule`.
service_resp_time_rule:
metrics-name: service_resp_time
op: ">"
threshold: 1000
period: 10
count: 3
silence-period: 5
message: Response time of service {name} is more than 1000ms in 3 minutes of
last 10 minutes.
service_sla_rule:
# Metrics value need to be long, double or int
metrics-name: service_sla
op: "<"
threshold: 8000
# The length of time to evaluate the metrics
period: 10
# How many times after the metrics match the condition, will trigger alarm
count: 2
# How many times of checks, the alarm keeps silence after alarm triggered,
default as same as period.
silence-period: 3
message: Successful rate of service {name} is lower than 80% in 2 minutes of
last 10 minutes
service_resp_time_percentile_rule:
# Metrics value need to be long, double or int
metrics-name: service_percentile
op: ">"
threshold: 1000,1000,1000,1000,1000
period: 10
count: 3
 
 
告警规则配置项的说明:
Rule name:规则名称,也是在告警信息中显示的唯一名称。必须以 _rule 结尾,前缀可自定义
Metrics name:度量名称,取值为 oal 脚本中的度量名,目前只支持 long 、 double 和 int 类
型。
Include names:该规则作用于哪些实体名称,比如服务名,终端名(可选,默认为全部)
Exclude names:该规则作不用于哪些实体名称,比如服务名,终端名(可选,默认为空)
Threshold:阈值
OP: 操作符,目前支持 > 、 < 、 =
Period:多久告警规则需要被核实一下。这是一个时间窗口,与后端部署环境时间相匹配
Count:在一个Period窗口中,如果values超过Threshold值(按op),达到Count值,需要发送
警报
Silence period:在时间N中触发报警后,在TN -> TN + period这个阶段不告警。 默认情况下,它
和Period一样,这意味着相同的告警(在同一个Metrics name拥有相同的Id)在同一个Period内
只会触发一次
message:告警消息
在配置文件中预先定义的告警规则总结如下:
1. 在过去10分钟内服务平均响应时间超过1秒达3次
2. 在过去10分钟内服务成功率低于80%达2次
silence-period: 5
message: Percentile response time of service {name} alarm in 3 minutes of
last 10 minutes, due to more than one condition of p50 > 1000, p75 > 1000, p90 >
1000, p95 > 1000, p99 > 1000
service_instance_resp_time_rule:
metrics-name: service_instance_resp_time
op: ">"
threshold: 1000
period: 10
count: 2
silence-p
eriod: 5
messag
e
:
R
e
sp
o
n
se
t
im
e
of service instance {name} is more than 1000ms in 2
minutes of
l
a
st
1
0
m
i
n
ut
e
s
# Active
e
nd
p
o
i
n
t
re
l
a
t
ed
m
e
tr
ics alarm will cost more memory than service and
service i
n
st
a
n
ce
m
et
r
i
c
s
a
l
a
rm
.
# Because the number of endpoint is much more than service and instance.
#
# endpoint_avg_rule:
# metrics-name: endpoint_avg
# op: ">"
# threshold: 1000
# period: 10
# count: 2
# silence-period: 5
# message: Response time of endpoint {name} is more than 1000ms in 2 minutes
of last 10 minutes
webhooks:
# - http://127.0.0.1/notify/
# - http://127.0.0.1/go-wechat/
 
 
3. 在过去10分钟内服务90%响应时间低于1秒达3次
4. 在过去10分钟内服务的响应时间超过1秒达2次
5. 在过去10分钟内端点的响应时间超过1秒达2次
这些警告信息最终会在Skywalking-UI上展示,效果如下:
3.3.5.2 Webhook规则
Webhook配置其实是警告消息接收回调处理,我们可以在程序中写一个方法接收警告信息,Skywalking
会以 application/json 格式通过http请求发送,消息格式声明为:
List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage 。
字段如下:
scopeId, scope: 所有的scope实体在
org.apache.skywalking.oap.server.core.source.DefaultScopeDefine 里面声明。
name. 目标scope实体名称。
id0: scope实体ID,匹配名称。
id1: 不使用。
ruleName: 配置在 alarm-settings.yml 里面的规则名称.
alarmMessage: 告警信息.
startTime:触发告警的时间 示例:
[
{
"scopeId": 2,
"scope": "SERVICE_INSTANCE",
"name": "c00158f28efc45cd813e21b6b8848a3a@192.168.1.104 of hailtaxi-driver",
"id0": "aGFpbHpdmVy.1_YzAwMAMTkyLjE2OC4xLjEwNA\u003d\u003d",
"id1": "",
"ruleName": "service_instance_resp_time_rule",
"alarmMessage": "Response time of service instance
c00158f28efc45cd813e21b6b8848a3a@192.168.1.104 of hailtaxi-driver is more than
1000ms in 2 minutes of last 10 minutes",
"startTime": 1611612258056
}
]
 
 
3.3.5.3 自定义Webhook消息接收
我们按照如下步骤,可以在自己程序中接收警告信息:
1)定义消息接收对象
在 hailtaxi-api 中创建
com.itheima.skywalking.model.AlarmMessage ,代码如下:
2)接收警告方法创建
在 hailtaxi-driver 中创建 com.itheima.driver.controller.AlarmMessageController 用于接收
警告消息,代码如下:
一般情况下,这种接收告警的api会被放置在比较清闲的后台服务中!!!
3)修改Webhook地址
修改 alarm-settings.yml 中的webhook地址:
@Data
@ToString
@AllArgsC
o
n
st
r
u
c
to
r
@NoArgsCo
n
st
ru
c
t
o
r
public class AlarmMessage {
private int scopeId;
private String name;
private String id0;
private String id1;
private String alarmMessage;
private long startTime;
String ruleName;
}
@RestController
@RequestMapping(value = "/skywalking")
public class AlarmMessageController {
/***
* 接收警告信息
* @param alarmMessageList
*/
@PostMapping("/webhook")
public void webhook(@RequestBody List<AlarmMessage> alarmMessageList) {
for (AlarmMessage alarmMessage : alarmMessageList) {
System.out.println("webhook:"+alarmMessage);
}
}
}
 
 
因为skywalking默认有一个告警规则:10分钟内服务成功率低于80%超过2次
所以为了能演示出告警效果,我们在 hailtaxi-driver 项目中的 driver/info 接口中添加一个一
句话
测试时将网关的条件断言给注释一下!!!
此时我们程序中就能接收警告信息了。
webhooks:
# - http://127.0.0.1/notify/
# - http://127.0.0.1/go-wechat/
- http://192.168.200.10:8001/driver/skywalking/webhook
/****
* 司
机信息
*/
//@
GetMapping(value = "/info/{id}")
@RequestMapping(value = "/info/{id}")
public Driver info(@PathVariable(value = "id")String
id,HttpServletRequest request){
int i = 1/ 0; // 产生异常
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()){
String name = headerNames.nextElement();
String value = request.getHeader(name);
System.out.println(name+":"+value);
System.out.println("--------------------------");
}
return driverService.findById(id);
}
 
 
 
posted @ 2023-05-13 23:47  十一vs十一  阅读(98)  评论(0编辑  收藏  举报