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
  • skywalking 镜像制作 skywalking js_java


  • skywalking 镜像制作 skywalking js_apache_02

  • 修改端口
  • skywalking 镜像制作 skywalking js_服务端_03

  • 使用mysql进行持久化
  • 打开配置文件 config -> application.yml
  • skywalking 镜像制作 skywalking js_java_04


  • skywalking 镜像制作 skywalking js_java_05

  • 修改配置文件中 storage 的配置
  • 修改selector: ${SW_STORAGE:mysql}
  • skywalking 镜像制作 skywalking js_学习_06

  • 修改mysql配置
  • skywalking 镜像制作 skywalking js_java_07

  • 在数据库中创建对应的数据库,所有需要用到的表会在启动SkyWalking服务端的时候完成创建。
  • 需要使用mysql进行持久化,需要在 oap-libs 中添加 mysql-connector-java 驱动包。
  • skywalking 镜像制作 skywalking js_apache_08

  • 服务端搭建完成,运行startup.bat文件。bin -> startup.bat
  • skywalking 镜像制作 skywalking js_java_09


  • skywalking 镜像制作 skywalking js_服务端_10

注:如果加入驱动,启动SkyWalking服务端表没有创建,可以多试试不同版本的驱动。

启动成功后,数据库中会创建SkyWalking需要的全部表。

skywalking 镜像制作 skywalking js_skywalking 镜像制作_11


SkyWalking控制台

skywalking 镜像制作 skywalking js_服务端_12


到这里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);
        });
    }
}
  • 收到告警回调请求,默认的告警时间有点久,可以多等待一会。