一、skywalking agent
1.1 skywalking agent探针
探针表示集成到目标系统中的代理或 SDK 库,即收集并格式化数据, 并发送到后端 包括链路追踪和性能指标.
通过地址: Downloads | Apache SkyWalking 可以下载得到你所需要的各个版本.这里选择 Java 9.1.0版本.
1.2 skywalking java agent目录
下载完成之后,直接解压即可,解压完成之后的目录结构如下图所示:
-
logs:skywalking agent的相关运行日志
-
bootstrap-plugins:插件包
-
optional-plugins:插件包(可供选择的插件包,如果需要生效则需要拷贝到plugins包下)
-
plugins:插件包(生效的插件包,支持多个框架链路追踪)
-
optional-reporter-plugins:插件包
-
activations:插件包
-
config: 配置文件
-
skywalking-agent.jar:agent代理的jar包
【主要是使用这个jar包】
1.3 skywalking 配置姿势
当项目开发完毕之后,可以通过java -jar进行部署,此时可以添加如下的参数,对skywalking agent进行配置.
配置姿势一:
bash
-javaagent:../skywalking-agent.jar=agent.service_name=app名称,collector.backend_service=127.0.0.1:11800
配置姿势二:
bash
-javaagent: ../skywalking-agent.jar -Dskywalking.agent.service_name=应用名称 -Dskywalking.collector.backend_service=127.0.0.1:11800
-
agent.service_name:客户端服务名,
在apm系统中显示的服务名称
-
collector.backend_service:skywalking上传数据的服务地址
-
优先级从高到低依次是:
-
JVM配置
-
环境变量配置
-
agent.config 【最低】
-
windows下配置示例:
- skywalking java agent解压目录,假设放到桌面,如下所示:
此时可以按照如下的方式进行配置,注意路径写法:
bash
-javaagent:C:\Users\rj\Desktop\skywalking-agent\skywalking-agent.jar -Dskywalking.agent.service_name=SkyWalkingApp -Dskywalking.collector.backend_service=0.0.0.0:11800
以上的方式都是打包之后,部署的时候,指定skywalking java agent,我们也可以在idea当中进行配置.
【重要说明】: 搭建一个简单的spring boot工程,进行简单的服务调用即可.假设这一步你已经完成.
选择【Add VM options】
配置成功
注意事项:
-
agent.service_name:客户端服务名,在apm系统中显示的服务名称,可以自己指定一个
-
collector.backend_service: SkyWalking上传数据的的服务地址, 也就是安装了OAP-server的服务器的ip地址或者域名.
二、skywalking使用实操
2.1 基本使用
配置好skywalking agent之后,直接启动项目,猛烈的请求几次,观察skywalking ui数据变化.
global面板展示:
service面板展示:
Instance面板展示:
EndPoint面板展示:
拓扑图:
链路追踪:
链路追踪页面和拓扑图页面根据服务及调用关系的不同,展示的是不一样的,具体取决于你的项目.通过上边的图可以发现,整个skywalking可以正常的、有效的工作了.
2.2 自定义链路追踪配置
-
我们可以针对具体的业务方法进行细粒度的链路追踪.
-
默认的追踪方式只能追踪具体的服务与数据库相关的链路,对于一个服务内的
业务方法
我们可以自己定义追踪.
理解一下TraceID和Span Id:
TraceID
用来标记一条记录链路,一条请求链路中包含一个Trace ID,多个Span ID,如下图所示:
我们可以对项目当中的某个业务进行【链路追踪】,方便问题的排查, 例如,在生产环境当中,请求某个接口较慢, 我们就可以根据自定义的链路追踪进行排查问题.
按照三层结构, controller -> service调用关系,记录当前业务当中的方法,将这些方法加入到链路当中,记录入参、出参等.
在刚才工程的当中或者新建一个普通的spring boot工程,三层结构走起, 引入如下依赖即可:
XML
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-trace</artifactId>
<version>8.12.0</version>
</dependency>
java
@GetMapping("/track")
public String track(){
userService.m1();
return "自定义链路追踪!";
}
service层代码,这里需要注意的是,此处代码没有任何实际意义,只是演示自定义链路追踪而已.
java
@Service
public class UserService {
@Trace
public void m1(){
System.out.println("m1 method");
m2();
}
@Trace
public void m2(){
System.out.println("m2 method");
m3();
}
@Trace
public void m3(){
System.out.println("m3 method");
}
}
在idea当中配置好skywalking java agent,启动项目,观察skywalking ui上的数据变化.
记录方法的入参及出参:
java
@Tags({
@Tag(key = "hello-input", value = "arg[0]"),
@Tag(key = "hello-output", value = "returnedObj")
})
在需要追踪的方法上,添加注解,注意事项如下所示:
- 不要导错包了
java
import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Tags;
- 参数含义:
-
value="arg[0]"表示方法的入参,
arg[0]
表示入参第一个参数,如果有第二个,则直接写arg[1]
,依次类推,如果业务方法没有入参,则可以省略不写. -
value = "returnedObj"表示方法出参,returnedObj为固定写法,表示出参.
-
如果入参、出参为对象 ,则实体类对象必须要重写
toString
方法
-
java
// service
@Trace
@Tags({
@Tag(key = "m4-input", value = "arg[0]"),
@Tag(key = "m4-output", value = "returnedObj")
})
public String m4(String s){
System.out.println("m4 method");
return "记录方法入参、出参!" + s;
}
// controller
@GetMapping("/m4")
public String m4(@RequestParam("s") String s){
return userService.m4(s);
}
猛烈请求接口,查看skywalking ui当中的【追踪】,找到请求的接口,具体操作如下所示:
2.3 性能剖析模块
操作步骤:
-
新建任务:
填入需要分析的端点
-
对任务进行采样
-
查看链路信息
-
性能分析: 查看对应方法的调用栈、找出可能会出问题的地方
-
一个服务在监控续续时间内只能设置一个端口监控任务
新建【性能分析】:
新建任务界面:
java
/**
* 性能监控
* 测试service
*/
public void m5(){
try {
TimeUnit.MILLISECONDS.sleep(2000);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("m45 method");
}
// 测试controller
@GetMapping("/m5")
public String m5(){
userService.m5();
return "性能监控!";
}
然后猛烈的请求接口,观察【性能剖析】页面
分析结果
注意事项:
- 性能剖析的接口,调用过程一定不能太快,
【尤其测试的时候, 最好在业务方法当中Thread.sleep()一下】
,如果接口,调用太快,则skywalking 无法采样,造成没有结果.
2.4 日志和rpc数据上报
应用场景:
-
用户请求接口,怎么在我们日志中找到traceId来跟踪系统调用链路
-
需要在系统日志打印出traceId
操作步骤:
- 引入依赖
- 配置logback
XML
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-toolkit-logback-1.x</artifactId>
<version>8.12.0</version>
</dependency>
配置logback打印日志(SpringBoot默认使用Logback)
,配置文件名 logback.xml
编写logback.xml
文件, 将当前输出的日志输出到控制台当中.配置内容如下所示:
XML
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志输出格式 -->
<property name="FILE_LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] %green(%-5level) [%thread] %yellow([%tid]) %cyan(%logger{50}) : %msg%n" />
<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>${FILE_LOG_PATTERN}</Pattern>
</layout>
</encoder>
</appender>
<!-- 异步输出 控制台 -->
<appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>256</queueSize>
<appender-ref ref="STDOUT"/>
</appender>
<root level="info">
<appender-ref ref="ASYNC_STDOUT"/>
</root>
</configuration>
在需要的地方打印日志.如下所示:
java
private Logger logger = org.slf4j.LoggerFactory.getLogger(UserService.class);
public void m5(){
try {
TimeUnit.MILLISECONDS.sleep(2000);
}catch (Exception e){
e.printStackTrace();
}
// System.out.println("m45 method");
logger.info("hello m5");
}
然后,猛烈的请求接口,在idea控制台查看结果.如下所示:
RPC数据上报:
如果要将数据上报到oap上,则需要修改skywalking-agent的配置文件,具体操作如下所示:
在配置文件末尾添加:
bash
# 指定要向其报告日志数据的GRPC服务器主机
plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:你的ip地址}
# 指定要向其报告日志数据的GRPC服务器端口
plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}
# 指定GRPC客户端要报告的日志数据的最大大小
plugin.toolkit.log.grpc.reporter.max_message_size=${SW_GRPC_LOG_MAX_MESSAGE_SIZE:10485760}
# 客户端向上游发送数据时将超时多长时间,单位是秒
plugin.toolkit.log.grpc.reporter.upstream_timeout=${SW_GRPC_LOG_GRPC_UPSTREAM_TIMEOUT:30}
修改日志文件logback.xml文件,添加如下内容:
XML
<!-- 使用gRpc将日志发送到skywalking服务端 -->
<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.TraceIdPatternLogbackLayout">
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</layout>
</encoder>
</appender>
<root level="info">
<appender-ref ref="ASYNC_STDOUT"/>
<appender-ref ref="GRPC_LOG"/>
</root>
完整的logback.xml文件如下所示:
XML
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志输出格式 -->
<property name="FILE_LOG_PATTERN" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] %green(%-5level) [%thread] %yellow([%tid]) %cyan(%logger{50}) : %msg%n" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- 配置了skywalking的traceId的日志打印的格式 -->
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</layout>
</encoder>
</appender>
<!-- 异步输出 控制台 -->
<appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>256</queueSize>
<appender-ref ref="STDOUT"/>
</appender>
<!-- 使用gRpc将日志发送到skywalking服务端 -->
<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.TraceIdPatternLogbackLayout">
<Pattern>${FILE_LOG_PATTERN}</Pattern>
</layout>
</encoder>
</appender>
<root level="info">
<appender-ref ref="ASYNC_STDOUT"/>
<appender-ref ref="GRPC_LOG"/>
</root>
</configuration>
猛烈请求接口,查看skywalking ui的【日志模块】.
点击日志,查看相关日志的详情:
2.5 告警模块和webhook
-
监控业务相关接口性能,超过阈值则触发告警功能
-
通过调用**
webhook接口进行触发
,具体的webhook接口地址可以自行定义路径
**- 注意:要
OAP Server
的网络可以触发的webhook接口
- 注意:要
-
开发人员可以在webhook接口中编写告警方式,比如邮件、短信等,它本质上就是一个http接口而已.
-
Apache Skywalking**
默认的告警规则配置
**-
安装目录下的config文件夹下 alarm-settings.yml文件
, 如果是docker容器,则进入到容器当中去找到相关的配置文件即可
-
默认内置多个规则
-
最近3分钟内服务的平均响应时间超过1秒
-
最近2分钟服务成功率低于80%
-
最近3分钟90%服务响应时间超过1秒
-
最近2分钟内服务实例的平均响应时间超过1秒
-
-
在alarm-settings.yml当中,找到最下边,配置自己的接口.【特别注意】: 这个接口必须得能让skywalking能调用到.如果使用的是云服务器,则本地服务要么打包到云服务器上去,要么去折腾内网穿透去,总之,必须得能使skywalking服务器访问我们自己编写的接口.
alarm-settings.yml配置文件当中的一些重要的配置,这里的配置大部分不需要我们自己调整,如果要调整则需要根据自己的业务进行调整即可.
-
metrics-name: 脚本中的度量名称
-
threshold: 阈值
-
op: 比较操作符,可以设定>,<,=
-
period: 多久检查一次当前的指标数据是否符合告警规则,单位分钟
-
count: 达到多少次后,触发告警消息
-
silence-period: 在多久时间之内,忽略相同的告警消息,在时间T触发了某告警,那么在(T+10)这个时间段,不会再次触发相同告警
-
message: 告警消息内容
-
webhooks: 配置告警产生时的触发的调用地址
bash
service_resp_time_rule(服务响应时间规则):
metrics-name: 指定要监控的指标名称为service_resp_time,表示服务的响应时间。
op: 操作符为 ">",表示当指标值大于后面的阈值时触发告警。
threshold: 阈值为 1000,即当服务响应时间大于 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.",其中{name}会被替换为具体的服务名称。
定义本地接口步骤:
- 定义实体类,这个实体类由官方提供,不必更改.
- 定义webhook接口
java
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AlarmMessage {
private int scopeId;
private String scope;
private String ruleName;
private String name;
private String id0;
private String id1;
private String alarmMessage;
private long startTime;
}
编写webhooks接口:
java
@RestController
public class AlertMessageController {
private Logger logger = LoggerFactory.getLogger(AlertMessageController.class);
private List<AlarmMessage> message = new ArrayList<>();
@PostMapping("/webhooks")
public void webhooks(@RequestBody List<AlarmMessage> messageList){
logger.info("webhooks:{}", messageList);
// todo: 收到消息之后,可以发送短信、邮件等其它业务处理.【结合自己的业务处理即可】
message.addAll(messageList);
}
@GetMapping("/show")
public List<AlarmMessage> getMessage(){
return message;
}
}
编写业务接口:
java
public void m5(){
try {
TimeUnit.MILLISECONDS.sleep(2000);
}catch (Exception e){
e.printStackTrace();
}
// System.out.println("m45 method");
logger.info("hello m5");
}
这里的方法延迟2s钟执行,这样会触发告警信息.请求几次接口,等三分钟, 查看是否收到了webhooks;
结果查看:
- 控制台输出
bash
INFO [XNIO-1 task-2] [TID:f78c724f54b143088784f307b5aec6a7.139.17270940166880001] com.rj.controller.AlertMessageController : webhooks:[AlarmMessage(scopeId=2, scope=SERVICE_INSTANCE, ruleName=service_instance_resp_time_rule, name=0d5ce315eb60407f819d5f800c0fa02f@192.168.200.56 of rj-skywalking-app, id0=cmotc2t5d2Fsa2luZy1hcHA=.1_MGQ1Y2UzMTVlYjYwNDA3ZjgxOWQ1ZjgwMGMwZmEwMmZAMTkyLjE2OC4yMDAuNTY=, id1=, alarmMessage=Response time of service instance 0d5ce315eb60407f819d5f800c0fa02f@192.168.200.56 of rj-skywalking-app is more than 1000ms in 2 minutes of last 10 minutes, startTime=1727094016588), AlarmMessage(scopeId=6, scope=ENDPOINT_RELATION, ruleName=endpoint_relation_resp_time_rule, name=User in User to GET:/m5 in rj-skywalking-app, id0=VXNlcg==.0_VXNlcg==, id1=cmotc2t5d2Fsa2luZy1hcHA=.1_R0VUOi9tNQ==, alarmMessage=Response time of endpoint relation User in User to GET:/m5 in rj-skywalking-app is more than 1000ms in 2 minutes of last 10 minutes, startTime=1727094016588)]
- 告警模块输出信息:
- 查看告警信息:
三、总结
本文主要介绍了skywalking 的一些基础概念及常用的操作,希望可以帮助到需要的同学.
全文完.