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下载安装包
解压,进入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库
在oap-libs中上传mysql驱动
进入bin目录运行startup.bat,启动后在浏览器打开链接http://localhost:18081/
可以看到,在mysql里已经自动创建了很多表
二. 整合Skywalking
下载Skywalking探针,在以下链接下载https://www.apache.org/dyn/closer.cgi/skywalking/java-agent/8.14.0/apache-skywalking-java-agent-8.14.0.tgz
解压后待使用,我的目录是: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
多次重复刷新接口,发现在控制台页面出现了服务监控数据
点击具体服务,点击服务名称customer,可以查看详情
为此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.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的APM文件目录,进入config目录,打开alarm-settings.yml,这个文件就是大部分默认的监控规则,我们只需改改参数即可使用
下面我们改下红框里面的规则,原来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,在控制台告警页面可以看到告警信息了
下面我们通过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对微服务的监控的初步集成的使用讲解结束。