当前位置:   article > 正文

Spring cloud alibaba--SkyWalking链路追踪_springcloudalibaba链路追踪

springcloudalibaba链路追踪

目录 

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

官网:Apache SkyWalking

下载:Downloads | Apache SkyWalking

文档:https://skywalking.apache.org/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脚本:
 

  1. #SkyWalking Agent配置
  2. export SW_AGENT_NAME=springboot-skywalking-demo #Agent名字,一般使用‘spring.application.name’
  3. export SW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800 #配置Collector地址
  4. export SW_AGENT_SPAN_LIMIT=2000 #配置链路的最大Span数量,默认是300
  5. export JAVA_AGENT=-javaagent:/usr/local/soft/apache-skywalking-apm-bin-es7/agent/skywalking-agent.jar
  6. java $JAVA_AGENT -jar springboot-skywalking-demo-0.0.1-SNAPSHOT.jar #jar启动
3.2windos环境--在IDEA中配置SkyWalking

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

  1. -javaagent:D:\software\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar
  2. -DSW_AGENT_NAME=api-service
  3. -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中引入依赖

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

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

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

 

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

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

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

  1. @RequestMapping("/add")
  2. @Trace
  3. @Tag(key = "add",value ="returnedObj")
  4. public String add() {
  5. System.out.println("下单成功");
  6. // String forObject = restTemplate.getForObject("http://localhost:8083/stock/reduct", String.class);
  7. String forObject = restTemplate.getForObject("http://stock-service/stock/reduct", String.class);
  8. //int a= 1/0;
  9. return "add order " + forObject;
  10. }
  11. @RequestMapping("/getById/{id}")
  12. @Trace
  13. @Tags({@Tag(key = "getById",value ="returnedObj"),
  14. @Tag(key="param",value = "arg[0]")
  15. })
  16. public String getById(@PathVariable("id") Integer id) {
  17. return "根据id获取信息";
  18. }

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

 

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

还可以记录参数

 

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

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

 

 

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

 

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

 

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

 

 7.Skywalking集成日志框架

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

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

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

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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <configuration>
  3. <!--引入spring boot默认的logback xml配置文件-->
  4. <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
  5. <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
  6. <!--日志的格式化-->
  7. <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
  8. <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
  9. <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
  10. </layout>
  11. </encoder>
  12. </appender>
  13. <!--设置Appender-->
  14. <root level="INFO">
  15. <appender-ref ref="console"/>
  16. </root>
  17. </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的配置

  1. <appender name="grpc-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
  2. <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
  3. <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
  4. <Pattern>%d{-yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n </Pattern>
  5. </layout>
  6. </encoder>
  7. </appender>
  8. <!--设置Appender-->
  9. <root level="INFO">
  10. <appender-ref ref="console"/>
  11. <appender-ref ref="grpc-log"/>
  12. </root>

 logback-spring.xml完整配置:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <configuration>
  3. <!--引入spring boot默认的logback xml配置文件-->
  4. <!-- <include resource="/org/springframework/boot/logging/logback/defaults.xml"/>-->
  5. <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
  6. <!--日志的格式化-->
  7. <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
  8. <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
  9. <Pattern>%d{-yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} </Pattern>
  10. </layout>
  11. </encoder>
  12. </appender>
  13. <appender name="grpc-log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
  14. <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
  15. <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
  16. <Pattern>%d{-yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n </Pattern>
  17. </layout>
  18. </encoder>
  19. </appender>
  20. <!--设置Appender-->
  21. <root level="INFO">
  22. <appender-ref ref="console"/>
  23. <appender-ref ref="grpc-log"/>
  24. </root>
  25. </configuration>

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

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

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

  1. plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:127.0.0.1}
  2. plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}
  3. plugin.toolkit.log.grpc.reporter.max_message_size=${SW_GRPC_LOG_MAX_MESSAGE_SIZE:10485760}
  4. 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>进行序列化的。

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

json格式例子:

  1. [{
  2. "scopeId": 1,
  3. "scope": "SERVICE",
  4. "name": "serviceA",
  5. "id0": "12",
  6. "id1": "",
  7. "ruleName": "service_resp_time_rule",
  8. "alarmMessage": "alarmMessage xxxx",
  9. "startTime": 1560524171000
  10. }, {
  11. "scopeId": 1,
  12. "scope": "SERVICE",
  13. "name": "serviceB",
  14. "id0": "23",
  15. "id1": "",
  16. "ruleName": "service_resp_time_rule",
  17. "alarmMessage": "alarmMessage yyy",
  18. "startTime": 1560524171000
  19. }]

1)写接收钩子函数的实体类

  1. /**
  2. * 警告类实体
  3. */
  4. public class AlarmMessageEntity {
  5. private int scopeId;
  6. private String scope;
  7. private String name;
  8. private String id0;
  9. private String id1;
  10. private String ruleName;
  11. private String alarmMessage;
  12. private List<Tag> tags;
  13. private long startTime;
  14. private transient int period;
  15. private transient boolean onlyAsCondition;
  16. public int getScopeId() {
  17. return scopeId;
  18. }
  19. public void setScopeId(int scopeId) {
  20. this.scopeId = scopeId;
  21. }
  22. public String getScope() {
  23. return scope;
  24. }
  25. public void setScope(String scope) {
  26. this.scope = scope;
  27. }
  28. public String getName() {
  29. return name;
  30. }
  31. public void setName(String name) {
  32. this.name = name;
  33. }
  34. public String getId0() {
  35. return id0;
  36. }
  37. public void setId0(String id0) {
  38. this.id0 = id0;
  39. }
  40. public String getId1() {
  41. return id1;
  42. }
  43. public void setId1(String id1) {
  44. this.id1 = id1;
  45. }
  46. public String getRuleName() {
  47. return ruleName;
  48. }
  49. public void setRuleName(String ruleName) {
  50. this.ruleName = ruleName;
  51. }
  52. public String getAlarmMessage() {
  53. return alarmMessage;
  54. }
  55. public void setAlarmMessage(String alarmMessage) {
  56. this.alarmMessage = alarmMessage;
  57. }
  58. public List<Tag> getTags() {
  59. return tags;
  60. }
  61. public void setTags(List<Tag> tags) {
  62. this.tags = tags;
  63. }
  64. public long getStartTime() {
  65. return startTime;
  66. }
  67. public void setStartTime(long startTime) {
  68. this.startTime = startTime;
  69. }
  70. public int getPeriod() {
  71. return period;
  72. }
  73. public void setPeriod(int period) {
  74. this.period = period;
  75. }
  76. public boolean isOnlyAsCondition() {
  77. return onlyAsCondition;
  78. }
  79. public void setOnlyAsCondition(boolean onlyAsCondition) {
  80. this.onlyAsCondition = onlyAsCondition;
  81. }
  82. @Override
  83. public String toString() {
  84. return "AlarmMessageEntity{" +
  85. "scopeId=" + scopeId +
  86. ", scope='" + scope + '\'' +
  87. ", name='" + name + '\'' +
  88. ", id0='" + id0 + '\'' +
  89. ", id1='" + id1 + '\'' +
  90. ", ruleName='" + ruleName + '\'' +
  91. ", alarmMessage='" + alarmMessage + '\'' +
  92. ", tags=" + tags +
  93. ", startTime=" + startTime +
  94. ", period=" + period +
  95. ", onlyAsCondition=" + onlyAsCondition +
  96. '}';
  97. }
  98. }

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

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

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

 访问接口告警信息

 

 

 参考文章:Spring cloud alibaba--SkyWalking链路追踪_springcloud链路追踪-CSDN博客

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号