Skywalking高级使用

news/2024/5/12 21:26:41/文章来源:https://blog.csdn.net/muriyue6/article/details/124959100

Skywalking高级使用

    • RPC调用监控
    • Mysql调用监控
    • Skywalking常用插件
    • 获取追踪ID
    • 过滤指定的端点
    • 告警功能
    • Skywalking原理
    • Open Tracing介绍

RPC调用监控

Skywalking(6.5.0)支持的RPC框架有以下几种:
(1) Dubbo 2.5.4 -> 2.6.0
(2) Dubbox 2.8.4
(3) Apache Dubbo 2.7.0
(4) Motan 0.2.x -> 1.1.0
(5) gRPC 1.x
(6) Apache ServiceComb Java Chassis 0.1 -> 0.5,1.0.x
(7) SOFARPC 5.4.0
我们使用Spring Boot和Dubbo搭建一个简单的服务提供方和服务消费方来测试Skywalking对于RPC调用的支持。

1、服务提供方
pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.10.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.itcast</groupId><artifactId>skywalking_dubbo_provider</artifactId><version>0.0.1-SNAPSHOT</version><name>skywalking_dubbo_provider</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--添加springboot和dubbo集成配置--><dependency><groupId>com.alibaba.spring.boot</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.0.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

这里直接使用了dubbo-spring-boot-starter这一dubbo与spring-boot集成的组件。
官方文档地址:https://github.com/alibaba/dubbo-spring-boot-starter/blob/master/README_zh.md

application.properties:

spring.application.name=skywalking_dubbo_provider
spring.dubbo.server=true
spring.dubbo.registry=N/A
server.port=8086

为了简化环境搭建,采用了本地直接调用的方式,所以将注册中心写成N/A表示不注册到注册中心。

IHelloService接口:

public interface IHelloService {public String hello();
}

简化项目的开发,将IHelloService接口在消费方和提供方都编写一份。

HelloServiceImpl实现类:

import com.alibaba.dubbo.config.annotation.Service;
import com.itcast.api.IHelloService;
import org.springframework.stereotype.Component;@Service(interfaceClass = IHelloService.class)
@Component
public class HelloServiceImpl implements IHelloService {@Overridepublic String hello() {return "hello skywalking";}
}

SkywalkingDubboProviderApplication启动类:

import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
//添加dubbo生效注解
@EnableDubboConfiguration
public class SkywalkingDubboProviderApplication {public static void main(String[] args) {SpringApplication.run(SkywalkingDubboProviderApplication.class, args);}}

需要添加@EnableDubboConfiguration注解。

2、服务消费方
pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.10.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.itcast</groupId><artifactId>skywalking_dubbo_consumer</artifactId><version>0.0.1-SNAPSHOT</version><name>skywalking_dubbo_consumer</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.alibaba.spring.boot</groupId><artifactId>dubbo-spring-boot-starter</artifactId><version>2.0.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.properties:

spring.application.name=skywalking_dubbo_consumer
server.port=8085

IHelloService接口:

public interface IHelloService {public String hello();
}

简化项目的开发,将IHelloService接口在消费方和提供方都编写一份。

TestController:

import com.alibaba.dubbo.config.annotation.Reference;
import com.itcast.api.IHelloService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class TestController {@Reference(url = "dubbo://127.0.0.1:20880")private IHelloService helloService;@GetMapping("/hello")public String hello(){return helloService.hello();}
}

采用直连而非从注册中心获取服务地址的方式,在@Reference注解中声明
url = “dubbo://127.0.0.1:20880”

SkywalkingDubboConsumerApplication启动类:

import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
//添加dubbo生效注解
@EnableDubboConfiguration
public class SkywalkingDubboConsumerApplication {public static void main(String[] args) {SpringApplication.run(SkywalkingDubboConsumerApplication.class, args);}}

需要添加@EnableDubboConfiguration注解。

3、部署方式
(1) 将skywalking_dubbo_consumer.jar和skywalking_dubbo_provider.jar上传至/usr/local/skywalking目录下。
(2) 首先我们复制两份agent,防止使用的冲突。

[root@skywalking skywalking]# cd /usr/local/skywalking/apache-skywalking-apm-bin/
[root@skywalking apache-skywalking-apm-bin]# cp -r agent agent_dubbo_provider
[root@skywalking apache-skywalking-apm-bin]# cp -r agent agent_dubbo_consumer
[root@skywalking apache-skywalking-apm-bin]# vi agent_dubbo_provider/config/agent.config

修改agent_dubbo_provider配置中的应用名为:

# The service name in UI
agent.service_name=${SW_AGENT_NAME:dubbo_provider}

接着修改agent_dubbo_consumer:

[root@skywalking apache-skywalking-apm-bin]# vi agent_dubbo_consumer/config/agent.config

修改应用名:

# The service name in UI
agent.service_name=${SW_AGENT_NAME:dubbo_consumer}

(3) 先启动provider,等待启动成功。

#切换到目录下
[root@skywalking ~]# cd /usr/local/skywalking/
#启动provider
[root@skywalking skywalking]# java -javaagent:/usr/local/skywalking/apache-skywalking-apm-bin/agent_dubbo_provider/skywalking-agent.jar -jar skywalking_dubbo_provider.jar &

在这里插入图片描述
出现如图所示内容,应用就已经启动成功了。

(4) 启动consumer,等待启动成功。

#启动consumer
[root@skywalking skywalking]# java -javaagent:/usr/local/skywalking/apache-skywalking-apm-bin/agent_dubbo_consumer/skywalking-agent.jar -jar skywalking_dubbo_consumer.jar &

在这里插入图片描述

(5) 调用接口,接口地址为:http://虚拟机IP地址:8085/hello
(6) 此时如果页面显示
在这里插入图片描述
那么dubbo的调用就成功了。
(7) 打开skywalking查看dubbo调用的监控情况。
仪表盘:
在这里插入图片描述
目前 dubbo_provider 和 dubbo_consumer 的服务已经出现,同时出现了两个接口分别是:
1》/hello接口,是浏览器调用dubb_consumer的http接口
2》com.itcast.api.IHelloService.hello()是dubbo_consumer调用dubbo_provider的dubbo接口

拓扑图:
在这里插入图片描述
该图中已经表示出了一个调用的链路关系:
User(浏览器) ----> dubber_consumer ----> dubbo_provider
并且在服务的上方标识出了每个服务代表的内容,dubbo_consumer是SpringMvc的服务,而dubbo_provider是Dubbo的服务。

追踪:
在这里插入图片描述
在这里插入图片描述
追踪图中显示本次调用耗时19ms,其中dubbo接口耗时3ms,那么另外的16ms其实是SpringMVC接
口的开销,这样就能很好的评估出每个环节的耗时时间。

Mysql调用监控

1、使用docker启动Mysql
docker安装参考:CentOS7 中 Docker 的安装
虚拟机中已经安装了docker,我们先将docker启动:

systemctl start docker

使用docker命令启动mysql:

docker run -di --name=skywalking_mysql -p 33306:3306 -e MYSQL_ROOT_PASSWORD=123456 centos/mysql-57-centos7

在这里插入图片描述
MYSQL_ROOT_PASSWORD环境变量指定root的密码为123456

这样就可以在外部访问mysql了。使用工具连接mysql,端口为33306密码为123456。创建数据库:
在这里插入图片描述
在这里插入图片描述

执行建表语句:

CREATE TABLE `t_user` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(50) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

插入几条数据:

insert into `t_user`(`name`) values ('张三'),('李四'),('王五');

2、Spring Data JDBC访问Mysql

创建一个Spring Boot工程,集成Spring Data JDBC。
pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.10.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.itcast</groupId><artifactId>skywalking_mysql</artifactId><version>0.0.1-SNAPSHOT</version><name>skywalking_mysql</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

引入了 spring-boot-starter-data-jdbc , 由于使用了5.7的mysql版本,所以驱动版本固定为5.1.46。

pojo类:

import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;@Table("t_user")
public class User {@Idprivate Integer id;private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +'}';}
}

添加Table注解,修改表明为t_user。

dao接口:

import com.itcast.skywalking_mysql.pojo.User;
import org.springframework.data.repository.CrudRepository;public interface UserRepository extends CrudRepository<User, Integer> {
}

controller类:

import com.itcast.skywalking_mysql.dao.UserRepository;
import com.itcast.skywalking_mysql.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;
import java.util.List;@RestController
public class MysqlController {@Autowiredprivate UserRepository userRepository;@GetMapping("/users")public List<User> findAll(){List<User> result = new ArrayList<>();userRepository.findAll().forEach((user) -> {result.add(user);});return result;}
}

由于Spring Data JDBC的findAll方法返回的是一个迭代器,所以需要遍历迭代器将数据进行返
回。

启动类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SkywalkingMysqlApplication {public static void main(String[] args) {SpringApplication.run(SkywalkingMysqlApplication.class, args);}}

application.properties:

spring.datasource.url=jdbc:mysql://192.168.75.103:33306/skywalking??useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
server.port=8087

3、部署方式
(1) 将 skywalking_mysql.jar 上传至 /usr/local/skywalking 目录下。
(2) 首先我们复制agent,防止使用的冲突。

[root@skywalking ~]# cd /usr/local/skywalking/apache-skywalking-apm-bin/
[root@skywalking apache-skywalking-apm-bin]# cp -r agent agent_mysql
[root@skywalking apache-skywalking-apm-bin]# vi agent_mysql/config/agent.config

修改agent_mysql配置中的应用名为:

# The service name in UI
agent.service_name=${SW_AGENT_NAME:skywalking_mysql}

(3) 启动skywalking_mysql应用,等待启动成功。

#切换到目录下
[root@skywalking /]# cd /usr/local/skywalking/
#启动spring boot
[root@skywalking skywalking]# java -javaagent:/usr/local/skywalking/apache-skywalking-apm-bin/agent_mysql/skywalking-agent.jar -jar skywalking_mysql.jar &

(4) 调用接口,接口地址为:http://虚拟机IP地址:8087/users
(5) 此时如果页面显示
在这里插入图片描述
那么mysql的调用就成功了。

(6) 打开skywalking查看mysql调用的监控情况。
服务仪表盘:
在这里插入图片描述

数据库仪表盘:
在这里插入图片描述
点击数据库仪表盘可以看到详细的数据库响应时长、吞吐量、SLA等数据。

拓扑图:
在这里插入图片描述
该图中已经表示出了一个调用的链路关系:
User(浏览器) ----> skywalking_mysql ----> localhost:33306
并且在服务的上方标识出了每个服务代表的内容,skywalking_mysql是SpringMVC的服务,而localhost:33306是mysql的服务。

追踪:
在这里插入图片描述
追踪图中显示本次调用耗时950ms,其中spring MVC接口耗时948ms,那么另外的2ms是调用Mysql的耗时。
点击mysql的调用,可以看到详细的sql语句。
在这里插入图片描述
这样可以很好的定位问题产生的原因,特别是在某些sql语句执行慢的场景下。

Skywalking常用插件

1、配置覆盖
在之前的案例中,我们每次部署应用都需要复制一份agent,修改其中的服务名称,这样显得非常麻烦。可以使用Skywalking提供的配置覆盖功能通过启动命令动态指定服务名,这样agent只需要部署一份即可。Skywalking支持的几种配置方式:
(1) 系统配置(System properties)
使用skywalking. + 配置文件中的配置名作为系统配置项来进行覆盖。
1》为什么需要添加前缀?
agent的系统配置和环境与目标应用共享,所以加上前缀可以有效的避免冲突。
2》案例
通过如下进行agent.service_name的覆盖

-Dskywalking.agent.service_name=skywalking_mysql

(2) 探针配置(Agent options)
Add the properties after the agent path in JVM arguments.

-javaagent:/path/to/skywalking-agent.jar=[option1]=[value1],[option2]=[value2]

1》案例
通过如下进行agent.service_name的覆盖

-javaagent:/path/to/skywalking-agent.jar=agent.service_name=skywalking_mysql

2》特殊字符
如果配置中包含分隔符(,或者=),就必须使用引号包裹起来

-javaagent:/path/to/skywalking-agent.jar=agent.ignore_suffix='.jpg,.jpeg'

3、系统环境变量(System environment variables)
1》案例
由于agent.service_name配置项如下所示:

# The service name in UI
agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}

可以在环境变量中设置SW_AGENT_NAME的值来指定服务名。

4、覆盖优先级
探针配置 > 系统配置 > 系统环境变量 > 配置文件中的值

所以我们的启动命令可以修改为:

java -javaagent:/usr/local/skywalking/apache-skywalking-apm-bin/agent_mysql/skywalking-agent.jar -Dskywalking.agent.service_name=skywalking_mysql -jar skywalking_mysql.jar &

或者

java -javaagent:/usr/local/skywalking/apache-skywalking-apm-bin/agent_mysql/skywalking-agent.jar=agent.service_name=skywalking_mysql -jar skywalking_mysql.jar &

获取追踪ID

Skywalking提供我们Trace工具包,用于在追踪链路时进行信息的打印或者获取对应的追踪ID。我们使用Spring Boot编写一个案例进行测试。
pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.10.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.itcast</groupId><artifactId>skywalking_plugins</artifactId><version>0.0.1-SNAPSHOT</version><name>skywalking_plugins</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><skywalking.version>6.5.0</skywalking.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--skywalking trace工具包--><dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-trace</artifactId><version>${skywalking.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

添加了对应的坐标:

<!--skywalking trace工具包-->
<dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-trace</artifactId><version>${skywalking.version}</version>
</dependency>

本案例中使用6.5.0的版本号。

PluginController类:

import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class PluginController {//获取trace id,可以在RocketBot追踪中进行查询@GetMapping("/getTraceId")public String getTraceId(){//使当前链路报错,并且提示报错信息ActiveSpan.error(new RuntimeException("Test-Error-Throwable"));//打印info信息ActiveSpan.info("Test-Info-Msg");//打印debug信息ActiveSpan.debug("Test-debug-Msg");return TraceContext.traceId();}
}

使用TraceContext.traceId()可以打印出当前追踪的ID,方便在RocketBot中进行搜索。
ActiveSpan提供了三个方法进行信息的打印:
(1) error方法会将本次调用变为失败状态,同时可以打印对应的堆栈信息和错误提示。
(2) info方法打印info级别的信息。
(3) debug方法打印debug级别的信息。

部署方式
(1) 将skywalking_plugins.jar上传至/usr/local/skywalking目录下。
(2) 启动skywalking_plugins应用,等待启动成功。

java -javaagent:/usr/local/skywalking/apache-skywalking-apm-bin/agent/skywalking-agent.jar -Dskywalking.agent.service_name=skywalking_plugins -jar skywalking_plugins.jar &

(3) 调用接口,接口地址为:http://虚拟机IP地址:8088/getTraceId
(4) 此时如果页面显示
在这里插入图片描述
可以看到追踪ID已经打印出来,然后我们在RocketBot上进行搜索。
在这里插入图片描述
可以搜索到对应的追踪记录,但是显示调用是失败的,这是因为使用了ActiveSpan.error方法,点开追踪的详细信息:
在这里插入图片描述
异常的信息包含了以下几个部分:
1》事件类型为error
2》调用方法时传递的异常类型RuntimeException
3》调用方法时传递的异常信息Test-Error-Throwable
4》异常堆栈

通过上述内容,我们可以根据业务来定制调用异常时的详细信息。
在这里插入图片描述
除了异常信息之外,还有info信息和debug信息也都会打印。

过滤指定的端点

在开发过程中,有一些端点(接口)并不需要去进行监控,比如Swagger相关的端点。这个时候我们就
可以使用Skywalking提供的过滤插件来进行过滤。在skywalking_plugins中编写两个接口进行测试:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class FilterController {//此接口可以被追踪@GetMapping("/include")public String include(){return "include";}//此接口不可被追踪@GetMapping("/exclude")public String exclude(){return "exclude";}
}

部署方式
1、将skywalking_plugins.jar上传至/usr/local/skywalking目录下。
2、将agent中的/agent/optional-plugins/apm-trace-ignore-plugin-6.4.0.jar插件拷贝到plugins目录下。

[root@skywalking ~]# cd /usr/local/skywalking/apache-skywalking-apm-bin/agent
[root@skywalking agent]# cp optional-plugins/apm-trace-ignore-plugin-6.5.0.jar  plugins/apm-trace-ignore-plugin-6.5.0.jar

3、重启OAP程序

ps -ef | grep oap
kill -9 47218
./oapService.sh

4、启动skywalking_plugins应用,等待启动成功。

java -javaagent:/usr/local/skywalking/apache-skywalking-apm-bin/agent/skywalking-agent.jar -Dskywalking.agent.service_name=skywalking_plugins -Dskywalking.trace.ignore_path=/exclude -jar skywalking_plugins.jar &

这里添加-Dskywalking.trace.ignore_path=/exclude参数来标识需要过滤哪些请求,支持AntPath表达式:
/path/* , /path/** , /path/?
(1) ? 匹配任何单字符
(2) * 匹配0或者任意数量的字符
(3) ** 匹配0或者更多的目录

5、调用接口,接口地址为:
http://虚拟机IP地址:8088/exclude
http://虚拟机IP地址:8088/include
在这里插入图片描述
在这里插入图片描述

6、在追踪中进行查看:
在这里插入图片描述
exclude接口已经被过滤,只有include接口能被看到。

告警功能

1、告警功能简介
Skywalking每隔一段时间根据收集到的链路追踪的数据和配置的告警规则(如服务响应时间、服务响应时间百分比)等,判断如果达到阈值则发送相应的告警信息。发送告警信息是通过调用webhook接口完成,具体的webhook接口可以使用者自行定义,从而开发者可以在指定的webhook接口中编写各种告警方式,比如邮件、短信等。告警的信息也可以在RocketBot中查看到。

以下是默认的告警规则配置,位于skywalking安装目录下的config文件夹下alarm-setting.yml文件中:

rules:# Rule unique name, must be ended with `_rule`.service_resp_time_rule:metrics-name: service_resp_timeop: ">"threshold: 1000period: 10count: 3silence-period: 5message: 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 intmetrics-name: service_slaop: "<"threshold: 8000# The length of time to evaluate the metricsperiod: 10# How many times after the metrics match the condition, will trigger alarmcount: 2# How many times of checks, the alarm keeps silence after alarm triggered, default as same as period.silence-period: 3message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutesservice_p90_sla_rule:# Metrics value need to be long, double or intmetrics-name: service_p90op: ">"threshold: 1000period: 10count: 3silence-period: 5message: 90% response time of service {name} is more than 1000ms in 3 minutes of last 10 minutesservice_instance_resp_time_rule:metrics-name: service_instance_resp_timeop: ">"threshold: 1000period: 10count: 2silence-period: 5message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes
#  Active endpoint related metrics alarm will cost more memory than service and service instance metrics alarm.
#  Because the number of endpoint is much more than service and instance.
#
#  endpoint_avg_rule:
#    metrics-name: endpoint_avg
#    op: ">"
#    threshold: 1000
#  Active endpoint related metrics alarm will cost more memory than service and service instance metrics alarm.
#  Because the number of endpoint is much more than service and instance.
#
#  endpoint_avg_rule:
#    metrics-name: endpoint_avg
#    op: ">"
#    threshold: 1000
#    period: 10
#    count: 2
#    silence-period: 5
#    message: Response time of endpoint {name} is more than 1000ms in 2 minutes of last 10 minuteswebhooks:
#  - http://127.0.0.1/notify/
#  - http://127.0.0.1/go-wechat/

以上文件定义了默认的4种规则:
(1) 最近3分钟内服务的平均响应时间超过1秒
(2) 最近2分钟服务成功率低于80%
(3) 最近3分钟90%服务响应时间超过1秒
(4) 最近2分钟内服务实例的平均响应时间超过1秒

规则中的参数属性如下:

属性含义
metrics-nameoal脚本中的度量名称
threshold阈值,与metrics-name和下面的比较符号相匹配
op比较操作符,可以设定>,<,=
period多久检查一次当前的指标数据是否符合告警规则,单位分钟
count达到多少次后,发送告警消息
silence-period在多久之内,忽略相同的告警消息
message告警消息内容
include-names本规则告警生效的服务列表

webhooks可以配置告警产生时的调用地址。

2、告警功能测试代码
编写告警功能接口进行测试,创建skywalking_alarm项目。
AlarmController:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class AlarmController {//每次调用睡眠1.5秒,模拟超时的报警@GetMapping("/timeout")public String timeout(){try {Thread.sleep(1500);} catch (InterruptedException e) {e.printStackTrace();}return "timeout";}
}

该接口主要用于模拟超时,多次调用之后就可以生产告警信息。

WebHooks:

import com.itcast.skywalking_alarm.pojo.AlarmMessage;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;
import java.util.List;@RestController
public class WebHooks {private List<AlarmMessage> lastList = new ArrayList<>();@PostMapping("/webhook")public void  webhook(@RequestBody List<AlarmMessage> alarmMessageList){lastList = alarmMessageList;}@GetMapping("/show")public List<AlarmMessage> show(){return lastList;}
}

产生告警时会调用webhook接口,该接口必须是Post类型,同时接口参数使用RequestBody。参数格式为:
在这里插入图片描述

AlarmMessage:

public class AlarmMessage {private int scopeId;private String name;private int id0;private int id1;//告警的消息private String alarmMessage;//告警的产生时间private long startTime;public int getScopeId() {return scopeId;}public void setScopeId(int scopeId) {this.scopeId = scopeId;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getId0() {return id0;}public void setId0(int id0) {this.id0 = id0;}public int getId1() {return id1;}public void setId1(int id1) {this.id1 = id1;}public String getAlarmMessage() {return alarmMessage;}public void setAlarmMessage(String alarmMessage) {this.alarmMessage = alarmMessage;}public long getStartTime() {return startTime;}public void setStartTime(long startTime) {this.startTime = startTime;}@Overridepublic String toString() {return "AlarmMessage{" +"scopeId=" + scopeId +", name='" + name + '\'' +", id0=" + id0 +", id1=" + id1 +", alarmMessage='" + alarmMessage + '\'' +", startTime=" + startTime +'}';}
}

3、部署测试
首先需要修改告警规则配置文件,将webhook地址修改为:

webhooks:- http://127.0.0.1:8089/webhook

然后重启skywalking重启OAP程序

ps -ef | grep oap
kill -9 47218
./oapService.sh

(1) 将skywalking_alarm.jar上传至/usr/local/skywalking目录下。
(2) 启动skywalking_alarm应用,等待启动成功。

java -javaagent:/usr/local/skywalking/apache-skywalking-apm-bin/agent/skywalking-agent.jar -Dskywalking.agent.service_name=skywalking_alarm -jar skywalking_alarm.jar

(3) 不停调用接口,接口地址为:http://虚拟机IP:8089/timeout
在这里插入图片描述

(4) 直到出现告警:
在这里插入图片描述

(5) 查看告警信息接口:http://虚拟机IP:8089/show
在这里插入图片描述
从上图中可以看到,我们已经获取到了告警相关的信息,在生产中使用可以在webhook接口中对接短信、邮件等平台,当告警出现时能迅速发送信息给对应的处理人员,提高故障处理的速度。

Skywalking原理

1、java agent原理
上文中我们知道,要使用Skywalking去监控服务,需要在其VM参数中添加"-
javaagent:/usr/local/skywalking/apache-skywalking-apm-bin/agent/skywalking-agent.jar"。这里就使用到了java agent技术。

Java agent是什么?
Java agent是java命令的一个参数。参数javaagent可以用于指定一个jar包。
(1) 这个jar包的MANIFEST.MF文件必须指定Premain-Class项。
(2) Permain-Class指定的那个类必须实现premain()方法。

当Java虚拟机启动时,在执行main函数之前,JVM会先运行-javaagent所指定jar包内Premain-Class这个类的premain方法。

如何使用java agent?
(1) 定义一个MANIFEST.MF文件,必须包含Premain-Class选项,通常也会加入Can-Redefine-Classes和Can-Retransform-Classes选项。
(2) 创建一个Premain-Class指定的类,类中包含premain方法,方法逻辑由用户自己确定。
(3) 将premain的类和MANIFEST.MF文件打成jar包。
(4) 使用参数-javaagent:jar包路径启动要代理的方法。

2、搭建java agent工程
使用maven创建java_agent_demo工程:
在这里插入图片描述

在java文件夹下创建PreMainAgent类:

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.JavaModule;import java.lang.instrument.Instrumentation;public class PreMainAgent {/*** 在这个 premain 函数中,开发者可以进行对类的各种操作。* 1、agentArgs 是 premain 函数得到的程序参数,随同 “– javaagent”一起传入。与 main 函数不同的是,* 这个参数是一个字符串而不是一个字符串数组,如果程序参数有多个,程序将自行解析这个字符串。* 2、Inst 是一个 java.lang.instrument.Instrumentation 的实例,由 JVM 自动传入。** java.lang.instrument.Instrumentation 是 instrument 包中定义的一个接口,也是这个包的核心部分,* 集中了其中几乎所有的功能方法,例如类定义的转换和操作等等。* @param agentArgs* @param inst*/public static void premain(String agentArgs, Instrumentation inst) {System.out.println("=========premain方法执行1========");System.out.println(agentArgs);}/*** 如果不存在 premain(String agentArgs, Instrumentation inst)* 则会执行 premain(String agentArgs)* @param agentArgs*/public static void premain(String agentArgs) {System.out.println("=========premain方法执行2========");System.out.println(agentArgs);}
}

类中提供两个静态方法,方法名均为premain,不能拼错。

在pom文件中添加打包插件:

<build><plugins><plugin><artifactId>maven-assembly-plugin</artifactId><configuration><appendAssemblyId>false</appendAssemblyId><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><archive><!--自动添加META-INF/MANIFEST.MF --><manifest><addClasspath>true</addClasspath></manifest><manifestEntries><Premain-Class>PreMainAgent</Premain-Class><Agent-Class>PreMainAgent</Agent-Class><Can-Redefine-Classes>true</Can-Redefine-Classes><Can-Retransform-Classes>true</Can-Retransform-Classes></manifestEntries></archive></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build>

该插件会在自动生成META-INF/MANIFEST.MF文件时,帮我们添加agent相关的配置信息。

使用maven的package命令进行打包:
在这里插入图片描述
打包成功之后,复制打包出来的jar包地址。
在这里插入图片描述

3、搭建主工程
使用maven创建java_agent_user工程:
在这里插入图片描述
Main类代码:

public class Main {public static void main(String[] args) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Hello World");}
}

先运行一次,然后点击编辑MAIN启动类:
在这里插入图片描述

在VM options中添加代码:
在这里插入图片描述

代码为:

-javaagent:D:\shipin\资料-分布式链路追踪skywalking\分布式链路追踪skywalking\代码\java_agent_demo\target\java-agent-demo-1.0-SNAPSHOT.jar=HELLOAGENT

启动时加载javaagent,指向上一节中编译出来的java agent工程jar包地址,同时在最后追加参数
HELLOAGENT。

运行MAIN方法,查看结果:
在这里插入图片描述
可以看到java agent的代码优先于MAIN函数的方法运行,证明java agent运行正常。

4、统计方法调用时间
Skywalking中对每个调用的时长都进行了统计,这一小节中我们会使用ByteBuddy和Java agent技术来统计方法的调用时长。
Byte Buddy是开源的、基于Apache 2.0许可证的库,它致力于解决字节码操作和instrumentation API的复杂性。Byte Buddy所声称的目标是将显示的字节码操作隐藏在一个类型安全的领域特定语言背后。通过使用Byte Buddy,任何熟悉Java编程语言的人都有望非常容易地进行字节码操作。Byte Buddy提供了额外的API来生成Java agent,可以轻松的增强我们已有的代码。

添加依赖:

<dependencies><dependency><groupId>net.bytebuddy</groupId><artifactId>byte-buddy</artifactId><version>1.9.2</version></dependency><dependency><groupId>net.bytebuddy</groupId><artifactId>byte-buddy-agent</artifactId><version>1.9.2</version></dependency>
</dependencies>

修改PreMainAgent代码:

public class PreMainAgent {public static void premain(String agentArgs, Instrumentation inst) {//创建一个转换器,转换器可以修改类的实现//ByteBuddy对java agent提供了转换器的实现,直接使用即可AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() {public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule) {return builder// 拦截任意方法.method(ElementMatchers.<MethodDescription>any())// 拦截到的方法委托给TimeInterceptor.intercept(MethodDelegation.to(MyInterceptor.class));}};new AgentBuilder // Byte Buddy专门有个AgentBuilder来处理Java Agent的场景.Default()// 根据包名前缀拦截类.type(ElementMatchers.nameStartsWith("com.agent"))// 拦截到的类由transformer处理.transform(transformer).installOn(inst);}
}

先生成一个转换器,ByteBuddy提供了java agent专用的转换器。通过实现Transformer接口利用builder对象来创建一个转换器。转换器可以配置拦截方法的格式,比如用名称,本例中拦截所有方法,并定义一个拦截器类MyInterceptor。

创建完拦截器之后可以通过Byte Buddy的AgentBuilder创造者来构建一个agent对象。AgentBuilder可以对指定的包名前缀来生效,同时需要指定转换器对象。

MyInterceptor类:

import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;import java.lang.reflect.Method;
import java.util.concurrent.Callable;public class MyInterceptor {@RuntimeTypepublic static Object intercept(@Origin Method method,@SuperCall Callable<?> callable)throws Exception {long start = System.currentTimeMillis();try {//执行原方法return callable.call();} finally {//打印调用时长System.out.println(method.getName() + ":" + (System.currentTimeMillis() - start)  + "ms");}}
}

MyInterceptor就是一个拦截器的实现,统计的调用的时长。参数中的method是反射出的方法对象,而
callable就是调用对象,可以通过callable.call()方法来执行原方法。
重新打包,执行maven package命令。接下来修改主工程代码。主工程将Main类放置到 com.agent 包
下。修改代码内容为:

package com.agent;public class Main {public static void main(String[] args) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Hello World");}
}

休眠1秒,使统计时长的演示效果更好一些。执行main方法之后显示结果:
在这里插入图片描述
我们在没有修改代码的情况下,利用java agent和Byte Buddy统计出了方法的时长,Skywalking的
agent也是基于这些技术来实现统计调用时长。

Open Tracing介绍

OpenTracing通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现。OpenTracing中最核心的概念就是Trace。

1、Trace的概念
在广义上,一个trace代表了一个事务或者流程在(分布式)系统中的执行过程。在OpenTracing标准中,trace是多个span组成的一个有向五环图(DAG),每一个span代表trace中被命名并计时的连续性的执行片段。
在这里插入图片描述

例如客户端发起的一次请求,就可以认为是一个Trace。将上面的图通过Open Tracing的语义修改完之后做可视化,得到下面的图:
在这里插入图片描述
图中每一个色块其实就是一个span。

2、Span的概念
一个Span代表系统中具有开始时间和执行时长的逻辑运行单元。span之间通过嵌套或者顺序排列建立逻辑因果关系。
Span里面的信息包括:操作的名字,开始时间和结束时间,可以附带多个key:value构成的Tags(key必须是String,value可以是String,bool或者数字),还可以附带Logs信息(不一定所有的实现都支持)也是key:value形式。

下面例子是一个Trace,里面有8个Span:
在这里插入图片描述
一个span可以和一个或者多个span间存在因果关系。OpenTracing定义了两种关系:Childof和FollowFrom。这两种引用类型代表了子节点和父节点间的直接因果关系。未来,OpenTracing将支持非因果关系的span引用关系。(例如:多个span被批量处理,span在同一个队列中,等等)
ChildOf很好理解,就是父亲Span依赖另一个孩子Span。比如函数调用,被调者是调用者的孩子,比如说RPC调用,服务端那边的Span,就是ChildOf客户端的。很多并发的调用,然后将结果聚合起来的操作,就构成了ChildOf关系。

如果父亲Span并不依赖于孩子Span的返回结果,这时可以说他构成FollowsFrom关系。
在这里插入图片描述
3、Log的概念
每个span可以进行多次Logs操作,每一次Logs操作,都需要一个带时间戳的时间名称,以及可选的任意大小的存储结构。
如下图是一个异常的Log
在这里插入图片描述
如下图是两个正常信息的Log,它们都带有时间戳和对应的事件名称、消息内容。
在这里插入图片描述
4、Tags的概念
每个span可以有多个键值对(key:value)形式的Tags,Tags是没有时间戳的,支持简单的对span进行注解和补充。

如下图就是一个Tags的详细信息,其中记录了数据库访问的SQL语句等内容。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_328237.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git gui教程---第四篇 Git gui的使用 添加文件,并提交

添加文件&#xff0c;并提交 新建一个txt文件点击扫描重新扫描&#xff0c;未缓存改动多了我们刚刚新建的文件。 点击缓存改动&#xff0c;文件位置变换。 如果缓存选错&#xff0c;想撤销&#xff0c;在菜单栏选择“提交”&#xff0c;“从本次提交撤销”&#xff0c;文件变更…

实例解释在lingo中使用集合模型

某部门有三个生产同一产品的工厂&#xff08;产地&#xff09;&#xff0c;生产的产品运往四个销售点&#xff08;销地&#xff09;出售&#xff0c;各个工厂的生产量、各销地的销量&#xff08;单位&#xff1a;吨&#xff09;、从各个工厂到各个销售点的单位运价&#xff08;…

动态规划之62 不同路径(第4道)

题目&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&…

debian to go

可以使用虚拟机操作&#xff0c;在运行镜像到安装步骤时选择 u盘 不需要手动分 /boot 分区之类的&#xff0c;“Automaction”自动分区就行&#xff0c;全安装到根目录。boot load 安装到 /dev/sdb&#xff0c;也就是硬盘本身 推荐使用gpt分区表&#xff0c;建议拿不用的盘练…

js实现图片压缩

创建一个type"file"的input标签&#xff0c;用于文件上传。 <input type"file" name"" id"upload" value"" />通过js实现图片压缩 window.onload function () {const upload document.getElementById("upload…

范德波尔方程可视化

Van der Pol方程如下所示 d x d t y d y d t − x ( 1 − x 2 ) y \begin{equation} \begin{aligned} \frac{dx}{dt} & y \\ \frac{dy}{dt} & -x(1-x^2)y \end{aligned} \end{equation} dtdx​dtdy​​y−x(1−x2)y​​​ 相应的程序如下 为了观看长期趋势&…

【LeetCode每日一题合集】2023.7.3-2023.7.9

文章目录 2023.7.3——445. 两数相加 II&#xff08;大数相加/高精度加法&#xff09;2023.7.4——2679. 矩阵中的和2023.7.5——2600. K 件物品的最大和&#xff08;贪心&#xff09;代码1——贪心模拟代码2——Java一行 2023.7.6——2178. 拆分成最多数目的正偶数之和&#x…

STM32的ADC模式及其应用例程介绍

STM32的ADC模式及其应用例程介绍 &#x1f4cd;ST官方相关应用笔记介绍资料&#xff1a;https://www.stmcu.com.cn/Designresource/detail/application_note/705947&#x1f4cc;相关例程资源包&#xff1a;STSW-STM32028&#xff1a;https://www.st.com/zh/embedded-software/…

MySQL数据库对象与数据备份和还原详解

目录 一、视图 1. 什么是视图 2. 视图与数据表的区别 3. 视图的优点 4. 创建视图 二、索引 1. 什么是索引 2. 为什么要使用索引 3. 索引优缺点 4. 何时不使用索引 5. 索引何时失效 6. 索引分类 6.1 普通索引 6.2 唯一索引 6.3 主键索引 6.4 组合索引 三、数据的…

Integration Objects OPC 所有产品Crack

OPC产品 OPC UA 升级到 OPC UA 以提高互操作性和安全性。 OPC 隧道 无需 DCOM 即可实现安全可靠的连接。 OPC 数据归档 将 OPC 数据存储到标准数据库或 CSV 文件中。 OPC 服务器 将任何通信协议转换为OPC标准。 OPC 客户端 读取、写入和传输您的 OPC 数据。 OPC 服务器工具…

axios的学习

axios是基于promise对ajax的一种封装 //将省份信息打印到网页上 <p class"my-p"></p> <script src"https://unpkg.com/axios/dist/axios.min.js"></script> <script>axios({url:http://hmajax.itheima.net/api/province}).…

图形学 | 期末复习(上)| games101笔记 | 补档

博客基于GAMES101-现代计算机图形学入门-闫令琪&#xff0c;但不是其完整笔记&#xff0c;基于复习要求有一定的删减。考试以图形学入门基本概念和核心研究内容为主&#xff0c;少量公式。即以论述概念为主&#xff0c;涉及少量算法。p1:29:12是对应的games101视频节点&#xf…

在阿里云上部署Springboot项目

文章目录 环境准备1.安装jdk2.安装mysql3.开启端口 上传项目1.数据库上传2.项目上传 环境准备 1.安装jdk 查看系统中原来是否含有java环境 rpm -qa |grep java rpm -qa |grep jdk rpm -qa |grep gcj其中&#xff0c;gcj是一个轻巧的&#xff0c;性能优越的Java语言编译器。它…

基于深度学习的高精度球场足球检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度球场足球检测识别系统可用于日常生活中或野外来检测与定位球场足球目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的球场足球目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5…

【考研408计算机组成原理】第三章存储系统 第五节cache

3.5.1工作原理 局部性原理&#xff1a;在最近可能会使用到周围的数据和指令。 性能分析&#xff1a;访问数据的时间 例题&#xff1a; 提出问题 知识总结 3.5.2 cache和主存的映射方式 3.5.3 替换算法 3.5.4 cache写策略

确保无缝、安全的云转型

随着云计算继续主导数字化转型&#xff08;这是理所当然的&#xff09;&#xff0c;组织面临着双重挑战&#xff1a;将运营无缝转移到云并确保这种转型的安全。 虽然云的采用保证了可扩展性、成本效率和生产力的提高&#xff0c;但保持警惕对于组织防范网络安全威胁和安全漏洞…

Nuxt3引入Element-plus和sass

1.引入Element-plus 打开编辑器终端 运行npm install element-plus/nuxt 或者命令行cd到项目文件 运行npm install element-plus/nuxt package.json文件会出现 使用Element-plus 在nuxt.config.ts文件添加代码 export default defineNuxtConfig({devtools: { enabled: true }…

<数据结构>NO9.选择类排序|直接选择排序|堆排序

文章目录 选择排序1.直接选择排序优化直接选择排序 2. 堆排序 选择排序 基本思想 选组排序是从待排序数据中选出最大/最小的元素放入到序列的起始位置&#xff0c;直到待排序数据全部有序。 直接选择排序和堆排序的基本思想均符合选择排序。 1.直接选择排序 假设数据按升序…

深入理解java虚拟机精华总结:硬件的效率与一致性、Java内存模型、Java与线程、Java与协程

深入理解java虚拟机精华总结&#xff1a;硬件的效率与一致性、Java内存模型、Java与线程、Java与协程 硬件的效率与一致性Java内存模型主内存与工作内存内存间交互操作对于volatile型变量的特殊规则针对long和double型变量的特殊规则原子性、可见性与有序性原子性可见性有序性 …

离线环境下安装微软Visual Studio 2022 生成工具

1. 前言 最近&#xff0c;在学习cython的时候&#xff0c;需要安装windows下的C/C编译、链接工具。开始觉得传统的msvc太大了&#xff0c;想要尝试Mingw&#xff0c;但是都是编译错误。无奈之下&#xff0c;还是要安装msvc。 微软提供了Visual Studio 2022 Build Tools &…