原文链接:SkyWalking/追踪/日志/告警/端点忽略/入门实例(dubbo+springBoot) – 编程屋

目录

1 什么是skyWalking       

2 环境和项目准备

3  项目环境启动

4 skyWalking展示

4.1 仪表盘,拓扑图、追踪

 4.2  追踪TraceId

5 忽略指定的端点

6 SkyWalking告警功能


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

Logo

快速构建 Web 应用程序

更多推荐