目录
1 什么是skyWalking
2 环境和项目准备
3 项目环境启动
4 skyWalking展示
4.1 仪表盘,拓扑图、追踪
4.2 追踪TraceId
5 忽略指定的端点
6 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优点报表功能比较完全,但是缺点代码侵入性很高。需要代码更改,对一些框架的使用需要埋点等操作。
此次项目用了skyWalking8.7.0,es做数据存储dubbo+zookeeper+SpringBoot+MyBatisPlus搭建了一个简易的框架。改项目由3个工程。一个公共类(dubbo_common),一个消费者(dubbo_consumer),一个提供者(dubbo_provider)组成。
dubbo_common:
一些项目公用依赖和实体类。公用依赖如下:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.3.8.RELEASE
com.liubujun.common
dubbo_common
1.0-SNAPSHOT
8
8
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
mysql
mysql-connector-java
8.0.19
com.baomidou
mybatis-plus-boot-starter
3.3.1
org.apache.dubbo
dubbo-spring-boot-starter
2.7.13
org.apache.curator
curator-framework
4.2.0
org.apache.curator
curator-x-discovery
4.2.0
jackson-databind
com.fasterxml.jackson.core
org.apache.skywalking
apm-toolkit-trace
8.7.0
org.apache.skywalking
apm-toolkit-logback-1.x
8.7.0
junit
junit
4.12
org.apache.maven.plugins
maven-surefire-plugin
2.22.2
dubbo_provider:
一些服务接口和服务实现类:
服务实现类:
@DubboService
public class OrderServiceImpl implements OrderService {
@Resource
private OrderMapper orderMapper;
@Override
public List getUser() {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("name","王美丽");
List 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 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);
}
}
我们以此启动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(我已踩坑)。
调用成功后,我们可以看到我们skyWalking的APM界面服务,端点。实例。
注意:刚进来可以有端点,但是没有数据点击UI界面右上角刷新按钮
拓扑图中我们可以清晰的看懂我们的调用链路(用户->消费者->生产者->数据库):
在追踪中我们同样也可以看到更加详细的信息,并且如果接口报错。可以看到报错日志。我们访问localhost:8081/
skyWalking其中的一个功能就是可以获取TraceId。我们能够根据tranceId获取我们具体的信息。如果我们功能上线之后,功能报错,这个时候能够提供给我们开发一个tranceId,我们能够很快的定位出问题。
想要获取需要先引入相关依赖(前面已引入)
注意:引入的版本号还是最好和skyWalking的版本相同
org.apache.skywalking
apm-toolkit-trace
8.7.0
//获取追踪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界面上
%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] %highlight(%5level) --- [%16.16thread] %cyan(%-40logger{40}) %4line : %msg%n
0
1024
true
%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n
访问:localhost:8081/getTraceId得到结果tranceId(tranceId字符串长度会有点长)
然后我们拿到tranceId在追踪中去搜索,可以很精确的匹配到我们的服务节点,并且可以观察他的调用日志。
但是大家可以发现我这个明明返回tranceId成功了,但是在追踪中却报红了,这是什么情况呢?原因是因为我们在调用的时候用了
ActiveSpan.error(new RuntimeException("Test-Error-Throwable"));
这个可以使当前链路报错,并且记录下来。当我们访问了接口之后,我们就可以在我们skyWalking的UI日志面板找到该端点的相应日志。
在我们平时的项目中,可能并不是所有的接口都需要我们去监控,所以我们需要将它排除在外,否则我们的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端点。
对于一套监控系统来说,告警功能是一套必不可少的功能。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 lastList = new ArrayList();
/**
* 从webhook接收告警信息
* @param alarmMessageList
*/
@PostMapping("/webhook")
public void webhook(@RequestBody List alarmMessageList){
lastList = alarmMessageList;
}
/**
* 用来验证RocketBot上的告警信息是否和接收到的是否一致
* @return
*/
@GetMapping("/show")
public List show(){
return lastList;
}
}
配置文件修改:
然后连续多次调用我们的接口,就可以在我们的RocketBot看到我们的告警信息
点击可查看详细信息:
好啦,关于skywalking的介绍就先告一段落。有问题欢迎留言指正。
源码下载地址:super/dubbo_skywalking