SkyWalking/追踪/日志/告警/端点忽略/入门实例(dubbo+springBoot)
1 什么是skyWalkingskyWalking是一个OAP(可观测分析平台)和APM系统(应用管理系统),它可以帮助我们理解系统行为,通过探针自动收集所需的指标,并进行分布式追踪。通过这些调用链路和指标,SkyWalkingAPM会感知应用间关系和服务间关系,并进行相应的指标统计。 以便发生故障的时候,能够快速定位和解决问题。例如:分布式和微服务框架下,一个用户请求有着多个调用。A->B
原文链接:SkyWalking/追踪/日志/告警/端点忽略/入门实例(dubbo+springBoot) – 编程屋
目录
1 什么是skyWalking
skyWalking是一个OAP(可观测分析平台)和APM系统(应用管理系统),它可以帮助我们理解系统行为,通过探针自动收集所需的指标,并进行分布式追踪。通过这些调用链路和指标,SkyWalkingAPM会感知应用间关系和服务间关系,并进行相应的指标统计。 以便发生故障的时候,能够快速定位和解决问题。
例如:分布式和微服务框架下,一个用户请求有着多个调用。A->B->C->D->E。当其中C服务出现异常,那么你的C->D->E也会出现异常。但是我们却不好定位是C服务出现异常,很难梳理,但分布式链路追踪却可以很好的解决这个问题。
像一些常见的分布式链路追踪系统:
PinPoint:UI界面元素多,用户体检感较好,并且实现了代码的零侵入,但是收集的数据较多,整体性能较差
SkyWalking:SkyWalking支持链路追踪和监控用用组件基本涵盖主流框架和容器,如国产的Dubbo和motan,国际化的spring boot和springcloud
CAT:CAT优点报表功能比较完全,但是缺点代码侵入性很高。需要代码更改,对一些框架的使用需要埋点等操作。
2 环境和项目准备
此次项目用了skyWalking8.7.0,es做数据存储dubbo+zookeeper+SpringBoot+MyBatisPlus搭建了一个简易的框架。改项目由3个工程。一个公共类(dubbo_common),一个消费者(dubbo_consumer),一个提供者(dubbo_provider)组成。
dubbo_common:
一些项目公用依赖和实体类。公用依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.liubujun.common</groupId>
<artifactId>dubbo_common</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<!--<scope>test</scope>-->
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version> <!-- Spring-Boot-Parent中已带版本,本可以不用带,但是用他中自带版本时,配置文件中Driver配置有错误-->
<!-- <version>8.0.22</version>版本Spring-Boot-Parent中已带-->
</dependency>
<!--不需要添加MyBatis及MyBatis-Spring的依赖,MyBatis-Plus会自动维护-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.13</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
<version>4.2.0</version>
<exclusions>
<exclusion>
<artifactId>jackson-databind</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
</exclusions>
</dependency>
<!--skyWalking监控相关-->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.7.0</version>
</dependency>
<!--skyWalking中的traceId记录到logback日志,我的skyWalking版本为8.5.0所以此处也选用了相同的版本-->
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.7.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<!--没有采用springBoot自带的打包插件,因为自带的插件打包会有问题。原因会在博客中详细记录-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<!-- <configuration>
<skipTests>true</skipTests>
</configuration>-->
</plugin>
</plugins>
</build>
</project>
dubbo_provider:
一些服务接口和服务实现类:
服务实现类:
@DubboService
public class OrderServiceImpl implements OrderService {
@Resource
private OrderMapper orderMapper;
@Override
public List<User> getUser() {
QueryWrapper<User> queryWrapper = new QueryWrapper();
queryWrapper.eq("name","王美丽");
List<User> users = orderMapper.selectList(queryWrapper);
return users;
}
}
服务接口就一个Service就不贴了。
注意:此处用了@DubboService暴露接口,没有采用xml文件的形式。
application.yml:
server:
port: 8082
dubbo:
application:
#采用协议方式和端口号
name: springboot-dubbo-provider
protocol:
#采用dubbo协议
name: dubbo
#发布dubbo的端口号为20883
port: 20883
registry:
address: zookeeper://localhost:2181
scan:
#dubbo实现类扫描范围
base-packages: com.liubujun.service
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/skywalking?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: lj123456
dubbo_consumer:
客户端调用类:
@RestController
public class ConsumerController {
@DubboReference
private OrderService orderService;
//测试消费方调用服务方
@RequestMapping("/getUser")
public List<User> getUser(){
return orderService.getUser();
}
//获取追踪Id,并可以在rocketBot中查询
@RequestMapping("/getTraceId")
public String getTraceId(){
//使当前链路报错,并提示报错信息
ActiveSpan.error(new RuntimeException("Test-Error-Throwable"));
//打印当前info信息
ActiveSpan.info("Test-Error-Throwable");
//打印debug信息
ActiveSpan.debug("Test-debug-Throwable");
//获取tranceId
return TraceContext.traceId();
}
@RequestMapping("/getError")
public void getError(){
int i = 1/0;
}
}
注意:此处用@DubboReference调用接口(之前一直用@Resource调用。虽然接口可以调通,但是在SkyWalking上只能显示客户端调用了消费者,不能显示消费者调用生产者)
application.yml:
server:
port: 8081
dubbo:
application:
name: springboot-dubbo-consumer
#采用协议方式和端口号
protocol:
#采用dubbo协议
name: dubbo
#发布dubbo的端口号为20882
port: 20882
registry:
address: zookeeper://localhost:2181
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/skywalking?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: lj123456
消费者和生产者启动类略有不同(此处指粘贴生产者,消费者不用扫描mapper文件):
@EnableDubbo
@SpringBootApplication
@MapperScan("com.liubujun.provider.mapper")
public class DubboProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DubboProviderApplication.class, args);
}
}
3 项目环境启动
我们以此启动zookeeper(zookeeper最好先启动服务端,再启动客户端),启动ES和skyWalking(先启动es,然后启动skyWalking)。最后启动生产者和消费者。消费者和生产者启动值前,需要在VM options中加入:
-javaagent:D:\usr\apache-skywalking-apm-es7-8.7.0\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar
-Dskywalking.agent.service_name=dubbo_consumer
-Dskywalking.collector.backend_service=127.0.0.1:11800
注释 -javaagent指定你下载的skyWalking中agent的绝对路径
-Dskywalking.agent.service_name 为将来在skyWalking中显示服务的名称
-Dskywalking.collector.backend_service skyWalking的服务地址
注意:此处为-Dskywalking.agent.service_name而不是-Dskywalking.agent.server_name(我已踩坑)。
4 skyWalking展示
4.1 仪表盘,拓扑图、追踪
访问本地的getUser接口
调用成功后,我们可以看到我们skyWalking的APM界面服务,端点。实例。
注意:刚进来可以有端点,但是没有数据点击UI界面右上角刷新按钮
拓扑图中我们可以清晰的看懂我们的调用链路(用户->消费者->生产者->数据库):
在追踪中我们同样也可以看到更加详细的信息,并且如果接口报错。可以看到报错日志。我们访问localhost:8081/
4.2 追踪TraceId
skyWalking其中的一个功能就是可以获取TraceId。我们能够根据tranceId获取我们具体的信息。如果我们功能上线之后,功能报错,这个时候能够提供给我们开发一个tranceId,我们能够很快的定位出问题。
想要获取需要先引入相关依赖(前面已引入)
注意:引入的版本号还是最好和skyWalking的版本相同
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.7.0</version>
</dependency>
//获取追踪Id,并可以在rocketBot中查询
@RequestMapping("/getTraceId")
public String getTraceId(){
//使当前链路报错,并提示报错信息
ActiveSpan.error(new RuntimeException("Test-Error-Throwable"));
//打印当前info信息
ActiveSpan.info("Test-Error-Throwable");
//打印debug信息
ActiveSpan.debug("Test-debug-Throwable");
//获取tranceId
return TraceContext.traceId();
}
除此之外,我们需要配置相关的logback-spring.xml文件,这样日志会打印在我们的控制台并且被skyWalking收集展示在我们的UI界面上
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--核心是encode的layout类是org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout-->
<!--pattern中的%tid是SkyWalking中的traceId-->
<appender name="STDOUT" 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] %highlight(%5level) --- [%16.16thread] %cyan(%-40logger{40}) %4line : %msg%n</pattern>
</layout>
</encoder>
</appender>
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>1024</queueSize>
<neverBlock>true</neverBlock>
<appender-ref ref="STDOUT"/>
</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>
<root level="INFO">
<appender-ref ref="grpc-log" />
<appender-ref ref="ASYNC"/>
</root>
</configuration>
访问:localhost:8081/getTraceId得到结果tranceId(tranceId字符串长度会有点长)
然后我们拿到tranceId在追踪中去搜索,可以很精确的匹配到我们的服务节点,并且可以观察他的调用日志。
但是大家可以发现我这个明明返回tranceId成功了,但是在追踪中却报红了,这是什么情况呢?原因是因为我们在调用的时候用了
ActiveSpan.error(new RuntimeException("Test-Error-Throwable"));
这个可以使当前链路报错,并且记录下来。当我们访问了接口之后,我们就可以在我们skyWalking的UI日志面板找到该端点的相应日志。
5 忽略指定的端点
在我们平时的项目中,可能并不是所有的接口都需要我们去监控,所以我们需要将它排除在外,否则我们的es数据收集会产生大量不必要的数据。因为我们skyWalking的插件里面并没有包含其相应的所有插件,而是将一部分插件放在了我们的agent目录下的optional-plugins文件夹下。所以如果我们想要用到此功能,需要将agent目录下\agent\optional-plugins\apm-trace-ignore-plugin-8.7.0.jar的插件拷贝到我们的agent目录下的\agent\plugins目录。为了测试,我们在controller新加入两个接口。
@RequestMapping("/include")
public String getInclude(){
return "没有忽略";
}
@RequestMapping("/ignore")
public String getIgnore(){
return "没有忽略";
}
然后在我们的idea 的 VM-Options的添加-Dskywalking.trace.ignore_path=/include
-javaagent:D:\usr\apache-skywalking-apm-es7-8.7.0\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar
-Dskywalking.agent.service_name=dubbo_consumer
-Dskywalking.collector.backend_service=127.0.0.1:11800
-Dskywalking.trace.ignore_path=/ignore
注意:添加此项命令是为了标识需要过滤哪些请求,如:/path/* (匹配0或任意数量的字符),/path/**(匹配0或更多的目录),/path/?(匹配任何单字符)
重启skyWalking和项目后 ,分别调用两个接口。调用完成之后,观察我们的skywalking发现其只有我们的include端点。
6 SkyWalking告警功能
对于一套监控系统来说,告警功能是一套必不可少的功能。skyWalking会将收集到链路追踪的数据和配置的告警规则进行比对。判断服务是否达到告警规则设置的级别,并发送相应的告警信息,发送告警信息时通过webhook接口完成。webhook接口我们可以自定义选择告警方式,例如:邮件,钉钉、短信。并且告警信息我们也可以在RocketBot中看到。在我们安装的skyWalking目录下\config\alarm-settings.yml默认的告警规则。
我们打开alarm-settings.yml文件发现其中有许多默认的告警规则,我们选择其中一条服务响应超时时间来看下:
当我们的接口达到我们配置的告警规则时,就会调用我们配置文件中的webhooks接口
然后为了方便,我们就来模拟服务调用超时告警。我们根据其默认规则中的超时告警规则,在过去的十分钟内超过3此调用超时1s钟。
相关代码:
超时方法:
@RestController
public class AlarmController {
/**
* 模拟超时报警
* @return
*/
@RequestMapping("/timeout")
public String timeout(){
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "timeout";
}
}
webhook相关接口:
@RestController
public class WebHooks {
private List<AlarmMessage> lastList = new ArrayList<AlarmMessage>();
/**
* 从webhook接收告警信息
* @param alarmMessageList
*/
@PostMapping("/webhook")
public void webhook(@RequestBody List<AlarmMessage> alarmMessageList){
lastList = alarmMessageList;
}
/**
* 用来验证RocketBot上的告警信息是否和接收到的是否一致
* @return
*/
@GetMapping("/show")
public List<AlarmMessage> show(){
return lastList;
}
}
配置文件修改:
以上只是部分内容,为了维护方便,本文已迁移到新地址:SkyWalking/追踪/日志/告警/端点忽略/入门实例(dubbo+springBoot) – 编程屋
源码下载地址:super/dubbo_skywalking
更多推荐
所有评论(0)