分布式链路追踪组件Skywalking
什么是Skywalking
SkyWalking是一个开源APM系统,包含了云原生架构下的分布式系统的监控、跟踪、诊断功能。
skywalking支持dubbo,SpringCloud,SpringBoot集成,代码无侵入,通信方式采用GRPC,性能较好,实现方式是java探针,支持告警,支持JVM监控,支持全局调用统计等等,功能较完善。
Skywalking和Spring Cloud Sleuth+ZipKin选型
Skywalking相比于zipkin还是有很大的优势的,如下:
- skywalking采用字节码增强的技术实现代码无侵入,zipKin代码侵入性比较高
- skywalking功能比较丰富,报表统计,UI界面更加人性化
Skywalking架构
skywalking分为服务端和客户端,服务端负责收集日志数据并且展示,架构如下
- 上面的Agent:负责收集日志数据,并且传递给中间的OAP服务器
- 中间的OAP:负责接收 Agent 发送的 Tracing 和Metric的数据信息,然后进行分析(Analysis Core) ,存储到外部存储器( Storage ),最终提供查询( Query )功能。
- 左面的UI:负责提供web控制台,查看链路,查看各种指标,性能等等。
- 右面Storage:负责数据的存储,支持多种存储类型。
大致流程就是Agent
负责收集日志传输数据,通过GRPC
的方式传递给OAP
进行分析并且存储到数据库中,最终通过UI界面
将分析的统计报表、服务依赖、拓扑关系图展示出来。
服务端搭建
下载安装包
Skywalking同样是通过Jar包启动,点击skywalking进入下载
Foundations
我们选择 V9.0.1
进行下载,Agents
选择 V8.11.0
下载,解压后完整目录如下:
配置修改
1、apache-skywalking-apm-bin\config下 application.yml
这个是 oap
服务的配置文件,需要修改注册中心为 nacos
,如下图:
2、apache-skywalking-apm-bin\webapp下 webapp.yml
这个是UI服务的配置文件,其中有一个 server.port
配置,是UI服务的端口,默认8080,避免端口冲突,修改为其他值:
3、启动服务
先将Nacos
启动,再启动Skywalking
服务,Skywalking启动命令在/bin目录下,这里需要启动两个服务,如下:
- oap服务:对应的启动脚本oapService.bat,Linux下对应的后缀是sh
- UI服务:对应的启动脚本webappService.bat,Linux下对应的后缀是sh
当然还有一个 startup.bat
启动文件,可以直接启动上述两个服务,我们可以直接使用这个脚本,直接双击,将会弹出两个窗口则表示启动成功,如下图:
然后浏览器直接访问:http://localhost:8888/general
目前还没有启动任何微服务,所以数据都是空的,接下来我们搭建客户端。
客户端搭建
由于Skywalking采用字节码增强技术,因此对于微服务无代码侵入,只要是普通的微服务即可,不需要引入什么依赖。
但是想要传输数据必须借助skywalking提供的agent,只需要在启动参数指定即可,命令如下:
-javaagent:G:\java\SpringCloud2020\Skywalking\skywalking-agent\skywalking-agent.jar
-Dskywalking.agent.service_name=cloud-gateway
-Dskywalking.collector.backend_service=127.0.0.1:11800
- -javaagent:指定skywalking中的agent中的
skywalking-agent.jar
的路径 - -Dskywalking.agent.service_name:指定在skywalking中的服务名称,一般是微服务的
spring.application.name
- -Dskywalking.collector.backend_service:指定oap服务绑定的地址,oap服务默认的端口是11800,因此只需要配置为
127.0.0.1:11800
上述参数可以在命令行通过java -jar xxx
指定,在IDEA中操作如下图:
上述三个微服务都需要配置skywalking的启动配置,配置成功后正常启动即可。
WARNING
注意:agent
的jar
包路径不能包含中文,不能有空格,否则运行不成功。
配置完成后启动服务,然后通过网关访问:http://localhost:9527/consumer/paymentSQL/1?uname=zhangsan
此时查看skywalking的UI端,可以看到几个微服务已经监控成功了,如下图:
服务之前的依赖关系也是可以很清楚的看到,如下图:
请求链路的信息也是能够很清楚的看到,比如请求的url,执行时间、调用的服务,如下图:
数据持久化配置
skywalking默认持久化的方式是存储在内存中,一旦服务重启则链路追踪数据就会丢失。skywalking提供了诸如ES、MySQL等方式进行数据的持久化,这里记录下使用MySQL进行数据持久化配置。
1、修改配置文件
同样的,修改apache-skywalking-apm-bin\config
下application.yml
storage:
selector: ${SW_STORAGE:mysql}
mysql:
properties:
jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:3306/skywalking?rewriteBatchedStatements=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC"}
dataSource.user: ${SW_DATA_SOURCE_USER:root}
dataSource.password: ${SW_DATA_SOURCE_PASSWORD:admin}
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}
2、添加MSQL的JDBC依赖
默认的oap
中是没有jdbc
驱动依赖,因此需要我们手动添加一下,只需要将驱动的jar放在oap-libs文件夹中,如下图:
配置完成后,在本地创建好skywalking数据库,然后再启动skywalking服务端
启动完成后,skywalking数据库中将会自动创建表,如下图:
日志监控
在skywalking的控制台上有一个日志菜单,用于收集客户端的日志,默认是没有数据的。
skywalking提供了主流的日志框架接入,像log4j,logback,log4j2等,这里将以logback为例子记录一下如何配置日志框架,以下是一些官方接入日志框架的文档:
1、添加依赖
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>${project.release.version}</version>
</dependency>
2、添加日志配置文件
新建一个logback-spring.xml
放在resource目录下
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod=" 5 seconds">
<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.mdc.TraceIdMDCPatternLogbackLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%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="ASYNC"/>
<appender-ref ref="grpc-log"/>
</root>
</configuration>
配置完成后,启动服务,打开skywalking控制台就能看见日志模块的输出。
注意:如果agent和oap服务不在同一台服务器上,需要在/agent/config/agent.config
配置文件末尾添加如下配置:
# 指定要向其报告日志数据的Grpc服务的主机,默认10.10.10.1
plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:10.10.10.1}
# 指定要向其报告日志数据的Grpc服务的端口,默认11800
plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}
# 指定Grpc客户端要报告的日志数据的最大大小,默认10485760
plugin.toolkit.log.grpc.reporter.max_message_size=${SW_GRPC_LOG_MAX_MESSAGE_SIZE:10485760}
# 客户端向上游发送数据时将超时多长时间,单位秒,默认30
plugin.toolkit.log.grpc.reporter.upstream_timeout=${SW_GRPC_LOG_GRPC_UPSTREAM_TIMEOUT:30}
监控告警
skywalking中有一些默认的告警规则,如下:
- 最近3分钟内服务的平均响应时间超过1秒
- 最近2分钟服务成功率低于80%
- 最近3分钟90%服务响应时间超过1秒
- 最近2分钟内服务实例的平均响应时间超过1秒
这些规则的配置在apache-skywalking-apm-bin/config/alarm-settings.yml
配置文件中
# Sample alarm rules.
rules:
# Rule unique name, must be ended with `_rule`.
service_resp_time_rule:
metrics-name: service_resp_time
op: ">"
threshold: 1000
period: 10
count: 3
silence-period: 5
message: Response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes.
service_sla_rule:
# Metrics value need to be long, double or int
metrics-name: service_sla
op: "<"
threshold: 8000
# The length of time to evaluate the metrics
period: 10
# How many times after the metrics match the condition, will trigger alarm
count: 2
# How many times of checks, the alarm keeps silence after alarm triggered, default as same as period.
silence-period: 3
message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes
service_resp_time_percentile_rule:
# Metrics value need to be long, double or int
metrics-name: service_percentile
op: ">"
threshold: 1000,1000,1000,1000,1000
period: 10
count: 3
silence-period: 5
message: Percentile response time of service {name} alarm in 3 minutes of last 10 minutes, due to more than one condition of p50 > 1000, p75 > 1000, p90 > 1000, p95 > 1000, p99 > 1000
service_instance_resp_time_rule:
metrics-name: service_instance_resp_time
op: ">"
threshold: 1000
period: 10
count: 2
silence-period: 5
message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes
database_access_resp_time_rule:
metrics-name: database_access_resp_time
threshold: 1000
op: ">"
period: 10
count: 2
message: Response time of database access {name} is more than 1000ms in 2 minutes of last 10 minutes
endpoint_relation_resp_time_rule:
metrics-name: endpoint_relation_resp_time
threshold: 1000
op: ">"
period: 10
count: 2
message: Response time of endpoint relation {name} is more than 1000ms in 2 minutes of last 10 minutes
webhooks:
# - http://127.0.0.1/notify/
# - http://127.0.0.1/go-wechat/
每个规则都由相同的属性组成,这些属性的含义如下图:
除了以上几种默认的规则,Skywalking还提供了webhooks方法,相当于一个回调,一旦触发了上述规则告警,skywalking则会调用配置的webhook,这就给开发者们提供了告警的后置处理,比如发送告警邮件、告警短信等等。
但是webhooks也有自己的一些规则:
- POST请求
- application/json 接收数据
- 接收的参数必须是AlarmMessage中指定的参数。
其中,AlarmMessage类不同版本可能会有所不同,需要自行找到对应版本的源码去拷贝其属性。对应的源码的路径:org.apache.skywalking.oap.server.core.alarm
。
新建一个告警模块,代码如下:
@RestController
@RequestMapping("alarm")
@Slf4j
public class AlarmController
{
@PostMapping("/receive")
public void receive(@RequestBody List<AlarmMessage> list)
{
log.info("处理一些通知告警事项");
log.info(JSON.toJSONString(list));
}
}
然后在apache-skywalking-apm-bin/config/alarm-settings.yml
中配置
webhooks:
# - http://127.0.0.1/alarm/receive