失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Spring cloud alibaba--SkyWalking链路追踪

Spring cloud alibaba--SkyWalking链路追踪

时间:2019-05-15 18:51:40

相关推荐

Spring cloud alibaba--SkyWalking链路追踪

目录

1.什么是SkyWalking

2.SkyWalking环境搭建部署

2.1下载skywalking

2.2启动服务

2.3访问前端ui页面

3.Skywalking接入微服务

3.1linux环境--通过jar包方式接入

3.2windos环境--在IDEA中配置SkyWalking

3.3wkywalking监控界面

3.4接入多个微服务

4.Skywalking持久化跟踪数据

4.1基于mysql的数据持久化

5.自定义skywalking链路追踪

6.性能剖析

7.Skywalking集成日志框架

8.skywalking告警

8.1告警规则

8.2webhook(网络钩子)

1.什么是SkyWalking

wkywalking是一个国产开源框架,由吴晟开源,加入Apache孵化器。skywalking是分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)框架而设计。它是一款优秀的APM(Application Performance Management)工具,包括了分布式追踪、性能指标分析、应用和服务依赖分析等。

官网:Apache SkyWalking

下载:Downloads | Apache SkyWalking

文档:/docs/main/v8.7.0/readme/

中文文档:SkyWalking 文档中文版(社区提供)

wkywaling主要功能特性:

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

(2)支持多种语言自动探针,包括Java,.net Core 和Node.js

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

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

(5)支持告警

(6)优秀的可视化解决方案

2.SkyWalking环境搭建部署

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

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

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

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

2.1下载skywalking

地址:Downloads | Apache SkyWalking

下载的版本提供elasticSearch和mysql等的版本,我们使用mysql版本的。下载tar压缩包,解压后目录:

目录结构:

①webapp:UI前端(web监控页面)的jar包和配置文件;

ui页面的启动端口,可以修改webapp.yml,默认是8080

②oap-libs:后台应用的jar包,以及它依赖的jar包,里边有一个server-starter-*.jar就是启动程序;

③config:启动后台应用程序的配置文件,是使用的各种配置

在application.yml中可以配置使用的存储方式等信息,默认使用h2内存方式

④bin:各种启动脚本,一般使用脚本startup.*来启动web页面和对应的后台应用;

oapService.*:默认使用的后台程序的启动脚本(使用的是默认启动模式);

oapServiceInit.*:使用init模式启动;在此模式下,OAP服务器启动以执行初始化工作,然后退出

oapServiceNoInit:使用no init模式启动;在此模式下,OAP服务器不进行初始化

webappService.*:UI前端的启动脚本;

startup.*:组合脚本,同时启动oapService.*,webappService.*脚本

⑤agent:

skywalking-agent.jar:代理服务jar包

config:代理服务启动时使用的配置文件

plugins:包含多个插件,代理服务启动时会加载该目录下的所有插件(实际是各种jar包)

optional-plugins:可选插件,当需要支持某种功能时,比如SpringCloud Gateway,则需要把对应的jar包拷贝到plugins目录下

2.2启动服务

双击bin/startup.bat启动服务,同时会启动oapservice和webapp两个服务

控制台没有答应启动是否成功以及端口等信息,当启动时会创建logs文件夹,分别生成skywalking-oap-server.log、webapp.log

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

2.3访问前端ui页面

根据webapp/webapp.yml中配置的ui的启动端口,访问ui页面

3.Skywalking接入微服务

3.1linux环境--通过jar包方式接入

准备一个springboot程序,打成可执行jar包,写一个shell脚本,在启动项目的Shell脚本上,通过-javaagent参数进行配置SkyWalking Agent来跟踪微服务;startup.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数量,默认是300export 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启动

3.2windos环境--在IDEA中配置SkyWalking

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

-javaagent:D:\software\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar-DSW_AGENT_NAME=api-service-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800

3.3wkywalking监控界面

启动系统,访问接口,此时查看skywalking监控页面,没有任何数据,当前服务下拉有配置的api-service服务。

没有显示任何链路追踪信息的原因:agent/plugins目录中缺少gateway的jar包。

从agent/optional-plugins(扩展插件)中复制gateway的jar包到agent/plugins目录中。

重新启动skywalking服务,以及springboot项目服务,在访问接口服务,skywalking控制台有检测数据。

仪表盘:显示服务、端点、慢服务等

拓扑图(调用关系),user访问api-service,api-service调用的ip和端口,由于8084的服务还没有加入skywalking,所以此处只显示ip和端口

追踪:调用服务的链路追踪,以及消耗的时间长短

3.4接入多个微服务

为了访问数据库,order的服务我们访问seate的项目,在OrderSeataApplication启动类的VM options中添加wkywalking的配置:

在StockSeateApplication启动类的VM options中添加:

先启动seate、nacos服务,再启动这三个项目

此时nacos中是可以看到这几个服务的

访问接口服务,此时wkywalking控制台可以看到多个服务,多个调用的端点

拓扑图显示了从user开始调用api-service网关服务,网关服务调用order-seata,order-seate调用数据库以及调用stock-seata;stock-seata调用数据库

追踪:显示了服务调用的完整过程,以及花费的时间

4.Skywalking持久化跟踪数据

默认使用H2(内存)数据库存储,在config/application.yml中配置,重启服务后数据会丢失。

4.1基于mysql的数据持久化

(1)修改config/application.yml中的数据源为mysql

(2)修改config/application.yml中的mysql连接配置

(3)mysql中创建数据库,名字为(2)中配置的数据库名

(4)重新启动startup.bat,发现oap-service服务启动不成功,查看skywalking-oap-server.log日志,显示获取不到数据库驱动。

(5)从我们本地maven私服中复制一份mysql驱动,粘贴到wkywalking启动的oap-libs中

(6)启动程序,发现oap-service还是启动失败

需要在连接mysql数据库连接中添加时区serverTimezone=GMT

(7)启动startup.bat,启动程序,skywalking会默认往我们配置的swtest数据库中添加需要的表

(8)访问接口,skywalking控制台有记录

重新启动skywalking后,直接刷新控制台页面,之前的数据还是存在的

5.自定义skywalking链路追踪

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

(1)pom.xml中引入依赖

<!--skywalking工具类,跟服务安装包版本一致--><dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-trace</artifactId><version>8.5.0</version></dependency>

(2)调用链路要显示具体的方法,在调用的方法中添加注解@Trace

(3)wkywalking控制台调用链路显示类名到接口名的方法

(4)调用链路中显示返回值,以及参数值信息,使用@Tag或者@Tags

@Tag注解中key=方法名 value=returnedObj 返回值 agr[0] 参数

param标识参数,returnedObj标识返回值

@RequestMapping("/add")@Trace@Tag(key = "add",value ="returnedObj")public String add() {System.out.println("下单成功");// String forObject = restTemplate.getForObject("http://localhost:8083/stock/reduct", String.class);String forObject = restTemplate.getForObject("http://stock-service/stock/reduct", String.class);//int a= 1/0;return "add order " + forObject;}@RequestMapping("/getById/{id}")@Trace@Tags({@Tag(key = "getById",value ="returnedObj"),@Tag(key="param",value = "arg[0]")})public String getById(@PathVariable("id") Integer id) {return "根据id获取信息";}

(5)访问接口后,在追踪中点击方法名

记录了返回值的key为add,以及返回的value值

还可以记录参数

6.性能剖析

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

(1)一开始性能剖析菜单是没有内容的,需要添加剖析的接口;点击新建任务创建

(2)sleep接口中睡眠2秒,访问接口,查看skywalking控制台的性能剖析

选中接口/order/sleep,点击分析展开调用链路

调用链路展开后可以看到花费时间最久的代码

7.Skywalking集成日志框架

springboot默认的日志配置:logback-spring.xml

(1)在订单服务的pom.xml中引入依赖

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

(2)在订单服务的resources目录中添加logback-spring.xml配置文件,日志级别使用INFO。

<?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>${CONSOLE_LOG_PATTERN}</Pattern></layout></encoder></appender><!--设置Appender--><root level="INFO"><appender-ref ref="console"/></root></configuration>

(3)logback-spring.xml中的<Pattern>标签的内容填充值,trace的id配置[%tid]

<Pattern>%d{-yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} </Pattern>

程序启动时开始打应trace的id,由于没有访问过接口,所以为N/A

(4)当访问接口时,控制台会打印输出TID信息

(5)复制打应的tid可以去skywalking控制台中根据追踪id搜素记录

(6)此时日志板块中还是没有任何记录

(7)把生成的日志添加到skywalkin控制台:

使用gRPC报告程序可以将收集到的日志转发到skywalking oap服务器上。

①在logback-spring.xml中添加grpc的配置

<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>%d{-yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n </Pattern></layout></encoder></appender><!--设置Appender--><root level="INFO"><appender-ref ref="console"/><appender-ref ref="grpc-log"/></root>

logback-spring.xml完整配置:

<?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>%d{-yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} </Pattern></layout></encoder></appender><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>%d{-yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n </Pattern></layout></encoder></appender><!--设置Appender--><root level="INFO"><appender-ref ref="console"/><appender-ref ref="grpc-log"/></root></configuration>

②访问接口服务,查看skywalking控制台,此时日志页面出现访问的日志信息,包括程序启动的控制台日志信息,可以点击追踪id查看链路访问情况

.③若skywalking服务不是部署在本地机器上,则grpc上报需要做而外的配置才能把日志上报上去。

在agent/config目录下有agent.config配置文件,添加日志的grpc配置信息

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}

8.skywalking告警

skywalking告警功能在6.x版本中新增的,其核心由一组规则驱动,这些规则定义在config/alarm-settings.yml文件中。告警规则的定义分为两部分:

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

(2)Webhook(网络钩子):定义当警告触发时,哪些服务终端需要被告知。

8.1告警规则

skywalking的发行版会默认提供config/alarm-setting.yml文件,里面预先定义了一些常用的告警规则,如下:

①过去3分钟内服务平均响应时间超过1秒

②过去2分钟服务成功率低于80%

③过去3分钟内服务响应时间超过1s的百分比

④服务实例在过去2分钟内平均响应时间超过1s,并且实例名称和正则表示式匹配。

⑤过去2分钟内端点平均响应时间超过1秒。

⑥过去2分钟内数据库访问平均响应时间超过1秒

⑦过去2分钟内端点关系平均响应时间超过1秒

这些预定义的告警规则,打开config/alarm-setting.yml文件即可看到

告警规则配置说明:

.Rule name:规则名称,也是在告警信息中显示的唯一名称,必须以_rule结尾,前缀自定义

.Metrics name:度量名称

.Include names:该规则作用于哪些实体类名称,比如服务名、终端名(可选,默认全部)

.Exclude names:该规则不用于哪些实体名称,比如服务名、终端名(可选,默认为空)

.Threshold:阈值

.OP:操作符,目前支持>、<、=

.Period:多久告警规则需要被核实一下,

.Count:在一个Period窗口中,如果values超过Threshold值(按op),达到count值,则发送警报

8.2webhook(网络钩子)

webhook可以简单理解为是一种Web层面的回调机制,通常由一些事件触发,与代码中的事件回调类似,只不过是web层面的,由于是web层面的,所以当事件发生时,回调的不再是代码中的方法或者函数,而是服务接口。例如在告警这个场景中,告警就是一个事件。当该事件发生时,Skywalking就会自动去调用一个配置好的接口,该接口就是所谓的webhook。

Skywalking的告警消息会通过http请求进行发送,请求方法为post,Content-Type为application/json,其JSON数据是基于List<org.apache.skywalking.oap.server.core.alarm.AlarmMessage>进行序列化的。

官网参考:/apache/skywalking/blob/v8.5.0/docs/en/setup/backend/backend-alarm.md

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)写接收钩子函数的实体类

/*** 警告类实体*/public class AlarmMessageEntity {private int scopeId;private String scope;private String name;private String id0;private String id1;private String ruleName;private String alarmMessage;private List<Tag> tags;private long startTime;private transient int period;private transient boolean onlyAsCondition;public int getScopeId() {return scopeId;}public void setScopeId(int scopeId) {this.scopeId = scopeId;}public String getScope() {return scope;}public void setScope(String scope) {this.scope = scope;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getId0() {return id0;}public void setId0(String id0) {this.id0 = id0;}public String getId1() {return id1;}public void setId1(String id1) {this.id1 = id1;}public String getRuleName() {return ruleName;}public void setRuleName(String ruleName) {this.ruleName = ruleName;}public String getAlarmMessage() {return alarmMessage;}public void setAlarmMessage(String alarmMessage) {this.alarmMessage = alarmMessage;}public List<Tag> getTags() {return tags;}public void setTags(List<Tag> tags) {this.tags = tags;}public long getStartTime() {return startTime;}public void setStartTime(long startTime) {this.startTime = startTime;}public int getPeriod() {return period;}public void setPeriod(int period) {this.period = period;}public boolean isOnlyAsCondition() {return onlyAsCondition;}public void setOnlyAsCondition(boolean onlyAsCondition) {this.onlyAsCondition = onlyAsCondition;}@Overridepublic String toString() {return "AlarmMessageEntity{" +"scopeId=" + scopeId +", scope='" + scope + '\'' +", name='" + name + '\'' +", id0='" + id0 + '\'' +", id1='" + id1 + '\'' +", ruleName='" + ruleName + '\'' +", alarmMessage='" + alarmMessage + '\'' +", tags=" + tags +", startTime=" + startTime +", period=" + period +", onlyAsCondition=" + onlyAsCondition +'}';}}

(2)钩子函数调用的后台接口服务,controller控制层,必须使用post方法

@RestController@RequestMapping("/alarm")public class AlarmController {/*** 接收钩子函数的接口,必须使用POST方式,使用实体来接收参数* @param list*/@PostMapping(value="/receive")public void receive(@RequestBody List<AlarmMessageEntity> list){System.out.println("已经接收到告警消息:"+list.get(0).toString());}}

(3)在config/alarm-settings.yml中的webhooks中配置钩子函数

访问接口告警信息

如果觉得《Spring cloud alibaba--SkyWalking链路追踪》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。