SkyWalking是分布式链路调用服务监控组件,微服务上线后,需要监控运行指标,比如系统的吞吐量,服务响应时间,CPU内存暂用率,异常等信息,它通过Agent收集日志,可以把数据存储在ES,MySQL等介质中,

下面来说说简单的使用。

一. 搭建Skywalking运行环境

使用https://www.apache.org/dyn/closer.cgi/skywalking/9.4.0/apache-skywalking-apm-9.4.0.tar.gz下载安装包

skywalking 部署 mysql skywalking监控mysql_skywalking 部署 mysql

 

 

解压,进入webapp目录,打开application.yml

修改工作端口为18081,避免端口冲突

serverPort: ${SW_SERVER_PORT:-18081}

再进入config目录,打开application.yml,修改存储介质为MySQL,以mysql为例

storage:
  selector: ${SW_STORAGE:mysql}

修改MySQL具体配置信息

mysql:
    properties:
      jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:3306/swtest?rewriteBatchedStatements=true&serverTimezone=UTC"}
      dataSource.user: ${SW_DATA_SOURCE_USER:root}
      dataSource.password: ${SW_DATA_SOURCE_PASSWORD:password}
      dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}
      dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}
      dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}
      dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}
    metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}
    maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}
    asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}

在MySQL中创建swtest库

skywalking 部署 mysql skywalking监控mysql_skywalking 部署 mysql_02

 

在oap-libs中上传mysql驱动

skywalking 部署 mysql skywalking监控mysql_spring_03

 进入bin目录运行startup.bat,启动后在浏览器打开链接http://localhost:18081/

skywalking 部署 mysql skywalking监控mysql_skywalking 部署 mysql_04

 

 可以看到,在mysql里已经自动创建了很多表

skywalking 部署 mysql skywalking监控mysql_spring_05

 

 二. 整合Skywalking

下载Skywalking探针,在以下链接下载https://www.apache.org/dyn/closer.cgi/skywalking/java-agent/8.14.0/apache-skywalking-java-agent-8.14.0.tgz

skywalking 部署 mysql skywalking监控mysql_spring_06

 

 解压后待使用,我的目录是:H:\apache-skywalking-java-agent-8.14.0\skywalking-agent\skywalking-agent.jar

在项目启动命令中添加如下参数配置

-javaagent:H:\apache-skywalking-java-agent-8.14.0\skywalking-agent\skywalking-agent.jar 
-Dskywalking.agent.service_name=customer 
-Dskywalking.collector.backend_service=localhost:11800

多次重复刷新接口,发现在控制台页面出现了服务监控数据

skywalking 部署 mysql skywalking监控mysql_skywalking 部署 mysql_07

 

 点击具体服务,点击服务名称customer,可以查看详情

skywalking 部署 mysql skywalking监控mysql_skywalking 部署 mysql_08

 

 为此Skywalking安装配置成功,服务运行状态采集成功。

  三. 简单的链路监控

  首先准备以下四个服务

项目名

说明

providerForAB

端口9900

providerA

端口8181

providerB

端口8182

customer

端口8999

  四个项目的pom.xml配置成一样,如下:

<?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 https://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.6.11</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>customer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>customer</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version>
        <spring-cloud.version>2021.0.5</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!--skywalking traceId 记录到logback日志-->
        <dependency>
            <groupId>org.apache.skywalking</groupId>
            <artifactId>apm-toolkit-logback-1.x</artifactId>
            <version>8.7.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

需要说明的是,providerA和providerB两个项目不同的地方是端口号,由于在本机上避免端口冲突,而正式环境都是部署在不同机器上的,这是同一个服务的不同节点,不需要对端口号进行区分

providerA的配置文件如下:

server:
  port: 8181
  servlet:
    session:
      timeout: 1800
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: serviceProvider

providerB的配置文件如下:

server:
  port: 8182
  servlet:
    session:
      timeout: 1800
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: serviceProvider

customer的配置文件如下:

server:
  port: 8999
  servlet:
    session:
      timeout: 1800
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: customer

providerForAB的配置文件如下:

server:
  port: 9900
  servlet:
    session:
      timeout: 1800
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: providerForAB

在四个项目中的resource目录都添加logback-spring.xml文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">

    <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{HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} - %msg%n</pattern>
            </layout>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>

</configuration>

大家注意到[%tid]就是用来标识同一个请求的,四个服务启动后,控制台输出的tid都是N/A

skywalking 部署 mysql skywalking监控mysql_skywalking 部署 mysql_09

 

 

 在四个项目的启动参数都加上以下代码,其中skywalking.agent.service_name配置成具体的服务名,这里以customer服务为例:

-javaagent:H:\apache-skywalking-java-agent-8.14.0\skywalking-agent\skywalking-agent.jar 
-Dskywalking.agent.service_name=customer 
-Dskywalking.collector.backend_service=localhost:11800

多次访问http://localhost:8999/customerCall接口,此接口就是customer服务的接口,发现各个项目控制台中打印的tid是一致的,以下是从不同项目的摘出来的内容:

11:51:04.501 [TID:a652d39f60f147d2a3eb5277bb0a47b2.92.16795434645000001] [http-nio-8999-exec-5] INFO  c.e.spingbootlearn.controller.Demo - customer节点访问A或B节点
11:51:05.000 [TID:a652d39f60f147d2a3eb5277bb0a47b2.92.16795434645000001] [http-nio-8182-exec-9] INFO  c.e.spingbootlearn.controller.Demo - 通过B节点访问业务接口
11:51:06.052 [TID:a652d39f60f147d2a3eb5277bb0a47b2.92.16795434645000001] [http-nio-9900-exec-2] INFO  c.e.spingbootlearn.controller.Demo - providerForAB业务接口返回数据

进入Skywalking控制台界面,切换到trace标签页,可以看到请求在整个链路的处理流程,输入tid:a652d39f60f147d2a3eb5277bb0a47b2.92.16795434645000001

skywalking 部署 mysql skywalking监控mysql_spring_10

 

 这样我们就可以进行简单的链路追踪,查看经过节点的耗时,进行进一步排查。

四. 告警规则和告警信息发送

通过前文,我们基本把简单使用流程通过小例子演示完了,接下来看看如果得到告警反馈。

打开SkyWalking的APM文件目录,进入config目录,打开alarm-settings.yml,这个文件就是大部分默认的监控规则,我们只需改改参数即可使用

skywalking 部署 mysql skywalking监控mysql_ide_11

 

 

 下面我们改下红框里面的规则,原来10分钟内,请求响应时间超过1000毫秒3次以上报警,我们改成超过1毫秒且大于1次就报警,如下:

service_resp_time_rule:
    metrics-name: service_resp_time
    op: ">"
    threshold: 1
    period: 10
    count: 1
    silence-period: 5

重启Skywalking,在控制台告警页面可以看到告警信息了

skywalking 部署 mysql skywalking监控mysql_ide_12

 

 

 下面我们通过webhooks接收告警信息,后续可以在应用里处理信息发送短信息或email

首先创建告警信息类接收告警信息

public class AlermMsg {
    private int scopeId;
    private String name;
    private String id0;
    private String id1;
    private String alarmMessage;
    private long startTime;

    public int getScopeId() {
        return scopeId;
    }

    public void setScopeId(int scopeId) {
        this.scopeId = scopeId;
    }

    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 getAlarmMessage() {
        return alarmMessage;
    }

    public void setAlarmMessage(String alarmMessage) {
        this.alarmMessage = alarmMessage;
    }

    public long getStartTime() {
        return startTime;
    }

    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }
}

在customer项目创建接收接口

@PostMapping("/notify")
    public void notify(@RequestBody List<AlermMsg> msgs) {
        logger.error("接收到告警信息,开始处理,可以在此发送短信息或邮件通知");
        for (AlermMsg msg : msgs) {
            logger.error("告警时间:" + msg.getStartTime() + "告警消息:" + msg.getAlarmMessage());
        }
    }

修改alarm-settings.yml中的webhooks

webhooks:
    - http://127.0.0.1:8999/notify

如下图所示,我们的接口已经接收到告警信息推送

skywalking 部署 mysql skywalking监控mysql_skywalking 部署 mysql_13

 

 至此,整篇Skywalking对微服务的监控的初步集成的使用讲解结束。