一、SkyWalking简介
1.1 简介
分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计。提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。 SkyWalking的优势有:
- 多种监控手段。可以通过语言探针和 service mesh 获得监控是数据。
- 多个语言自动探针。包括 Java,.NET Core 和 Node.JS。
- 轻量高效。无需大数据平台,和大量的服务器资源。
- 模块化。UI、存储、集群管理都有多种机制可选。
- 支持告警。
- 优秀的可视化解决方案。
1.2 SkyWalking整体架构
在官网上有一张SkyWalking整体架构的图
我们可以把整个结构分为四部分:
- 上部分 Agent:负责从应用中,收集链路信息,发送给 SkyWalking OAP 服务器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 数据信息。SkyWalking目前采用的是,SkyWalking Agent 收集 SkyWalking Tracing 数据,传递给服务器。
- 下部分 SkyWalking OAP :负责接收 Agent 发送的 Tracing 数据信息,然后进行分析(Analysis Core) ,存储到外部存储器( Storage ),最终提供查询( Query )功能。
- 右部分 Storage :Tracing 数据存储。目前支持 ES、MySQL、Sharding Sphere、TiDB、H2 多种存储器。而我们SkyWalking采用的是 ES ,主要考虑是 SkyWalking 开发团队自己的生产环境采用 ES 为主。
- 左部分 SkyWalking UI :负责提供控台,查看链路等等。
1.3 SkyWalking单机环境
SkyWalking单机应用整体的框架如图
在日常使用中最简单的就是单机环境,SkyWalking的单机环境的搭建非常的简单,步骤罗列一下分为五步走:
- 搭建一个 Elasticsearch 服务。
- 下载 SkyWalking 软件包。
- 搭建一个 SkyWalking OAP 服务。
- 启动一个 Spring Boot 应用,并配置 SkyWalking Agent。
- 搭建一个 SkyWalking UI 服务。
二、SkyWalking环境搭建
2.1 Elasticsearch 搭建
前文说到,SkyWalking虽然支持多种数据存储,也有我们常用的MySQL,但是SkyWalking主要采用的还是Elasticsearch,所以哦我们首先要搭建一个Elasticsearch服务,Linux下安装ElasticSearch可以参考:# ElasticSearch简介与安装 ,我们本次采用在Windows下安装Elasticsearch。
下载解压后的全貌就是这样
进入bin目录下,双击执行elasticsearch.bat
双击后等一会发现好像启动好了,连网址都出现了
但是我们去访问:http://192.168.30.238:9200/ 的时候发现却是无法访问。
这是因为ssl地址访问到了默认地址,修改配置文件即可,进入config目录,在elasticsearch.yml中修改配置如下
我们需要将原来为true的值全部改为false,配置是这两个:
- xpack.security.enabled
- xpack.security.http.ssl:enabled
修改完后如图:
再重新启动试试,依然非常完美没有任何错误。
浏览器访问一下:http://192.168.30.238:9200/
启动好Elasticsearch服务后我们还有需要安装ElasticSearch-head插件,这个插件是为了更好的看到Elasticsearch服务的情况。安装ElasticSearch-head的前提是要有node环境,这个不再赘述,可以去网上看看。ElasticSearch-head插件插件的地址,这里官方也给出了步骤,我们按照步骤来即可。
下载完成后的本尊长这样
进入head文件夹下,执行命令:npm install,如果安装速度慢,设置成淘宝的镜像重新安装 npm config set registry registry.npm.taobao.org ,在安装完成后可以输入命令npm run start启动head插件。
访问后会发现未连接到es
因为我们还需要在es的配置文件中新增参数。进入config目录
找到elasticsearch.yml这个文件
在末尾追加两行新的参数:
# 增加新的参数,这样head插件可以访问es
http.cors.enabled: true
http.cors.allow-origin: "*"
修改完后重启ES即可。
到此为止ES已经安装完成。
2.2 SkyWalking安装
SkyWalking下载地址,应该在skywalking9版本以后将agent进行了单独拆分,因此若要使用9版本以后的,需要下载apm和agent两个压缩包。具体以官方为准。
此次我们下载的版本是9.5.0,分别下载apm和agent
分别把这两个tar.gz的包下载下来,如果觉得太卡的话可以用阿里的镜像下载。
下载完成后我们解压可以看看目录结构。
说两个比较重要的且常见的:
- bin:存放一些可执行的脚本,比如说启动Skywalking OAP服务的脚本
- config: 存放配置文件,这里是我们需要关注的,有OAP服务的配置文件
applicaiton.yml。
而agent长这样:
下面就可以开始启动服务了。双击apm的bin目录下的startup.bat,而Linux上是startup.sh
启动后发现啥也没有!接下来开始看日志排查。
2.3 SkyWalking报错排查
返回到安装目录下有一个logs的文件夹里面是日志,我们可以看到有一个skywalking-oap-server.log这个文件,可以发现确实是报错了,日志里面有一行
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: /127.0.0.1:17912
这说明 OAP Server 尝试连接 BanyanDB(作为存储后端)时失败了,因为 BanyanDB 没有运行或配置错误。SkyWalking 默认使用 H2 作为嵌入式存储,但是我们想用ES来存储,所以要改一下配置。我们进入到config目录下有一个application.yml这个文件,打开,搜索一下storage:时会发现,好家伙确实是用的是banyandb
但是底下其实是有elasticsearch可以选的,我们把banyandb改为elasticsearch试一下。
改完之后再重启一下,好家伙还是不行,接着看日志,可以发现这次的日志变了。
Caused by: java.lang.UnsupportedOperationException: Unsupported version: ElasticSearch 9.2
表面我们的数据库确实是换了,但是!SkyWalking 明确拒绝连接 Elasticsearch 9.2,因为它不支持这个版本。我们可以在官网的数据存储介绍中明确看到ES支持的版本是7-8,所以我们只需要降级一下版本即可。
我们直接去ES其他版本选择下载其他版本即可。要重复前文2.1的步骤,然后依旧完美启动。
再次启动,成功!
三、整合SpringBoot
整合最基础的是需要有一个简单的springboot的项目,这里不做过多赘述,如果要整合SkyWalking的话,我们还需要引入两个jar包。
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.9.0</version>
</dependency>
接下来就到另一个项目起作用了,还记得之前我们下载过另一个项目skywalking-agent吗?这个项目之前选择的是java版本,他就是来代理我们的java项目的。找到skywalking-agent/config/agent.config这个配置目录,我们需要做一些配置。
# 你的服务名称
agent.service_name=your-spring-boot-app
# SkyWalking OAP Server地址,改了就要改,没改就不用变
collector.backend_service=localhost:11800
将以下JVM参数添加到Spring Boot应用的启动命令中,以启用SkyWalking Agent,意味着我们的SkyWalking Agent的jar包启动的方式是探针部署。
这里要注意替换成你都jar包的位置
接着我们要模拟一个最简单的数据库交互的例子。比如我们的Controller
@RestController
class HelloController {
@Autowired
private DatabaseService databaseService;
@GetMapping("/hello")
public String sayHello() {
databaseService.queryData();
return "Hello, SkyWalking!";
}
}
对于的service
@Service
public class DatabaseService {
public void queryData() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
最后还有一步,那就是要配置一下日志输出,即对应的logback-spring.xml文件,这里给一个模板,具体可以自行拓展。
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="E:\code\idea-code\skywalkingDemo\skywalkingDemo" ></property>
<!-- 彩色日志 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<!--控制台日志, 控制台输出 -->
<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">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} [%X{tid}] %clr([%-10.10thread]){faint} %clr(%-5level) %clr(%-50.50logger{50}:%-3L){cyan} %clr(-){faint} %msg%n</pattern>
</layout>
</encoder>
</appender>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="TRACE" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.trace.TraceIdConverter">
<layout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg [TraceId: %traceId] %n</Pattern>
</layout>
</appender>
<!--文件日志, 按照每天生成日志文件 (只能是 由 Logger 或者 LoggerFactory 记录的日志消息哦)-->
<!--以下关于 日志文件的pattern 需要去掉颜色,防止出现 ANSI转义序列-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/pro.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%-10.10thread] %-5level %-50.50logger{50}:%-3L - %msg%n</pattern>
</layout>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--skywalking grpc 日志收集-->
<appender name="grpc" 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>
<appender-ref ref="FILE" ></appender-ref>
<appender-ref ref="grpc"/>
</root>
</configuration>
到这里后就可以开始启动我们的springboot项目了,看到控制台可以输出这个日志之后说明是我们的项目是正常启动了,并且是已经部署好了SkyWalking探针。
SkyWalking提供了一些注解,可以帮助我们自定义追踪逻辑。我们可以使用这些注解来标记需要监控的方法。比如我们在HelloController中加一个方法。
@GetMapping("/customMethod")
public String customMethod() {
customService.customMethod();
return "Hello, customMethod!";
}
同时新建一个service,并且加上@Trace这个注解,@Trace注解用于标记customMethod方法,使其成为一个可追踪的操作。TraceContext.traceId()方法可以获取当前追踪的ID,用于日志或其他用途。
@Service
public class CustomService {
@Trace(operationName = "customOperation")
public void customMethod() {
// Simulating a custom operation
System.out.println("TraceId: " + TraceContext.traceId());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
最后我们再启动的时候访问一下可以看到控制台输出了一个TraceId
我们可以把这个id复制下来去SkyWalking UI界面去看,我们可以看到好像多了一个可点击的栏,我们点击到对应的服务,点进去。
复制对于的traceId可以看到对于的日志追踪信息
到这里简单的整合已经完成。