SkyWalking是什么
SkyWalking 是一个开源可观测平台,用于收集、分析、聚合和可视化来自服务和云原生基础设施的数据。SkyWalking 提供了一种简单的方法来保持分布式系统的清晰视图,甚至跨云。它是一种现代 APM,专为云原生、基于容器的分布式系统而设计。
为什么要用SkyWalking
SkyWalking 为在许多不同场景中观察和监控分布式系统提供解决方案。首先,与传统方法一样,SkyWalking 为 Java、C#、Node.js、Go、PHP 和 Nginx LUA 等服务提供自动仪器代理。(呼吁 Python 和 C++ SDK 贡献)。在多语言、持续部署的环境中,云原生基础架构变得更加强大,但也更加复杂。SkyWalking 的服务网格接收器允许 SkyWalking 接收来自 Istio/Envoy 和 Linkerd 等服务网格框架的遥测数据,让用户了解整个分布式系统。
SkyWalking 为服务、服务实例、端点提供可观察性能力。如今,Service、Instance 和 Endpoint 等术语随处可见,因此值得在 SkyWalking 的上下文中定义它们的具体含义:
- 服务。表示为传入请求提供相同行为的一组/一组工作负载。您可以在使用仪器代理或 SDK 时定义服务名称。SkyWalking 还可以使用您在 Istio 等平台中定义的名称。
- 服务实例。服务组中的每个单独的工作负载都称为一个实例。就像pods在 Kubernetes 中一样,它不需要是单个操作系统进程,但是,如果您使用仪器代理,则实例实际上是一个真正的操作系统进程。
- 端点。用于传入请求的服务中的路径,例如 HTTP URI 路径或 gRPC 服务类 + 方法签名。
SkyWalking 允许用户了解Services 和Endpoints 的拓扑关系,查看每个Service/Service Instance/Endpoint 的指标,并设置报警规则。
此外,您还可以集成
其他使用带有 Zipkin、Jaeger 和 OpenCensus 的 SkyWalking 本地代理和 SDK 的分布式跟踪。
其他度量系统,如 Prometheus、Sleuth(Micrometer)、OpenTelemetry。
官方地址
官网地址:https://skywalking.apache.org/ 下载地址:https://skywalking.apache.org/downloads/ 文档地址:https://skywalking.apache.org/docs/ GitHub地址:https://github.com/apache/skywalking
下载SkyWalking
- 进入官方下载页面,下载相应的安装包。
搭建服务端
- SkyWalking的控制台端口默认为8080,可以通过配置文件修改端口。
- 打开配置文件 webapp -> webapp.yml
- 修改端口
- 使用mysql进行持久化
- 打开配置文件 config -> application.yml
- 修改配置文件中 storage 的配置
- 修改selector: ${SW_STORAGE:mysql}
- 修改mysql配置
- 在数据库中创建对应的数据库,所有需要用到的表会在启动SkyWalking服务端的时候完成创建。
- 需要使用mysql进行持久化,需要在 oap-libs 中添加 mysql-connector-java 驱动包。
- 服务端搭建完成,运行startup.bat文件。bin -> startup.bat
注:如果加入驱动,启动SkyWalking服务端表没有创建,可以多试试不同版本的驱动。
启动成功后,数据库中会创建SkyWalking需要的全部表。
SkyWalking控制台
到这里SkyWalking服务端搭建完成,并使用Mysql进行持久化。
微服务接入SkyWalking
在java客户端启动参数中添加
# skywalking-agent.jar jar包所在位置
-javaagent:E:\Devlop\skywalking\apache-skywalking-apm-bin-es7\agent\skywalking-agent.jar
# 自定义服务名
-DSW_AGENT_NAME=custom-skywalking-server
# SkyWalking 的 collector 服务的 IP 和端口
-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=127.0.0.1:11800
Gateway网关服务接入SkyWalking
除了添加启动参数外,还需要添加gateway插件。将 optional-plugins 中的 gateway 插件放入 plugins 目录中。
- 进入 agent 目录
- 进入 optional-plugins 目录
- 找到 gateway 插件
- 复制或者移动至 plugins 目录中
- 到这里 gateway 网关就接入成功了。接入成功就能看到,追踪、拓扑图等信息。
自定义链路追踪
- 添加依赖,跟服务端的版本一样就行。
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.7.0</version>
</dependency>
- 使用注解 @Trace 可以自定义追踪方法。
- 在SkyWalking中就能看到 findAll 方法就被追踪到了。
- 可以看到追踪方法的详细信息
- 还可以通过 @Tags 注解追到到调用方法的参数和返回值。@Tag 注解中 value 是固定写法
- arg:代表参数
- returnedObj:代表返回值
- 调用方法后,就能在SkyWalking中看到方法的参数和返回值了。
- 还有其他的一些手动追踪API,详情查看官方文档。
日志追踪
- 添加依赖,版本和服务端版本一致
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.7.0</version>
</dependency>
- 在项目 resource 目录中添加 logback-spring.xml。
- 配置 logback-spring.xml 内容,在日志中打印跟踪 ID。
- 在 Pattern 中添加 [%tid]
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<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>%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) [%tid] %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}</Pattern>
</layout>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
- 控制台就能打印出追踪ID。
- 通过追踪ID可以快速定位到追踪信息。
- 通过gRPC将收集到的日志转发到 SkyWalking OAP 服务器。
- 添加 GRPCLogClientAppender logback.xml
<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="STDOUT"/>
<appender-ref ref="grpc-log" />
</root>
- 打开配置文件 agent -> config -> agent.conf
- 在文件末尾添加配置
# Skywalking 服务端 IP 地址
plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:127.0.0.1}
# Skywalking 服务端 gRPC 端口
plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}
# 最大日志数据量
plugin.toolkit.log.grpc.reporter.max_message_size=${SW_GRPC_LOG_MAX_MESSAGE_SIZE:10485760}
# 超时时间 单位:s
plugin.toolkit.log.grpc.reporter.upstream_timeout=${SW_GRPC_LOG_GRPC_UPSTREAM_TIMEOUT:30}
- 重启 Skywalking 服务端,访问请求就能在控制台看到日志了。
- 可以直接从日志列表中的追踪ID直接定位追踪信息,更为方便。
性能剖析
- 在 Skywalking 控制台中的性能剖析中创建任务。断电名称为请求地址,其他信息默认就行。
- 在代码中添加请求,并让程序等待3秒。
- 由于最大采样数是5,因此测试时可以多点几次请求,5次以上。
- 点开单个样本中,然后点击分析按钮开始分析,可以直观的看到问题。
- 可以看到,Skywalking 直接定位到了问题代码。
告警
- 查看告警配置,打开配置文件 config -> alarm-settings.yml
- 在配置文件中可以看到多种告警条件。触发某一个条件就会告警。
- 配置文件中的告警条件可以自定义修改,也可以自行添加。
- 还可以在配置文件的 webhooks 添加自定义告警回调Web接口。
- 修改配置后,重启 Skywalking 服务端。
- 添加依赖,也可以在github上找到 AlarmMessage 实体类,放入项目中。
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>server-core</artifactId>
<version>8.7.0</version>
</dependency>
- 添加回调请求处理。
@RestController
@RequestMapping("/custom/alarm")
public class AlarmController {
@PostMapping("/fallback")
public void fallback(@RequestBody List<AlarmMessage> alarmMessages) {
alarmMessages.forEach(alarmMessage -> {
StringBuffer buffer = new StringBuffer();
buffer.append("scopeId:").append(alarmMessage.getScopeId()).append("\n");
buffer.append("scope:").append(alarmMessage.getScope()).append("\n");
buffer.append("scope 实体类 ID:").append(alarmMessage.getId0()).append("\n");
buffer.append("id1:").append(alarmMessage.getId1()).append("\n");
buffer.append("标签:").append(alarmMessage.getTags()).append("\n");
buffer.append("period:").append(alarmMessage.getPeriod()).append("\n");
buffer.append("scope 实体类名称:").append(alarmMessage.getName()).append("\n");
buffer.append("告警条件:").append(alarmMessage.getRuleName()).append("\n");
buffer.append("告警消息:").append(alarmMessage.getAlarmMessage()).append("\n");
buffer.append("告警时间:").append(alarmMessage.getStartTime()).append("\n");
System.out.println(buffer);
});
}
}
- 收到告警回调请求,默认的告警时间有点久,可以多等待一会。