Skywalking高级使用

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.hqwc.cn/news/14414.html

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

相关文章

Windows mingw64 最简易 安装配置

其实挺简单一件事 很多教程都搞复杂了 自己写一个 只需要两步 1. 下载压缩包并解压 2. 配置环境变量 (1). GitHub 下载地址 Releases niXman/mingw-builds-binaries GitHub 如果GitHub下载太慢可以来这里加速 或者用地址2 GitHub Proxy 代理加速 (ghproxy.com) (2). 下…

Vue3的使用--002

Vue3包含vue2的语法&#xff0c;学习vue3就行。 前提要求&#xff0c; 安装大于node.js15.0。 创建Vue 项目 &#xff1a; npm init Vuelastest : 这一执行将会安装并执行create-vue, 他是Vue 官方的脚手架工具。你将会看到一些Typescript 和测试支持之类的可选功能提示&…

VTK STL 体积 表面积测量 最短路径 读取中文路径

目录 开发环境&#xff1a; vtkMassProperties 三、中文路径 数据读取 开发环境&#xff1a; 系统&#xff1a;Win10 VTK&#xff1a;8.2.0 Qt&#xff1a;5.12.4 一、结构化对象 体积 面积 vtkMassProperties VTK 计算体积和面积的主要类 vtkMassProperties vtkSm…

ArcGis Pro如何通过C#进行插件开发?

文章目录 0.引言1.开发工具准备2.VS&#xff08;C#&#xff09;创建ArcGIS Pro模块加载项3.编译并使用ArcGis Pro插件 0.引言 ArcGIS Pro插件&#xff08;Add-ins&#xff09;可以让用户更加容易的自定义和扩展ArcGIS Pro应用程序&#xff0c;它创建一系列自定义工具提供了一个…

[论文笔记] Gemini: A Computation-Centric Distributed Graph Processing System

Gemini: A Computation-Centric Distributed Graph Processing System Gemini: 以计算为中心的分布式图处理系统 [Paper] [Slides] [Code] OSDI’16 摘要 提出了 Gemini, 一个分布式图处理系统, 应用了多种针对计算性能的优化以在效率之上构建可扩展性. Gemini 采用: 稀疏-…

web3创业有哪些机会及具体案列(二)

目录 1. 去中心化金融&#xff08;DeFi&#xff09;&#xff1a;2. 去中心化身份验证和数字身份&#xff1a;3. 去中心化市场和电子商务&#xff1a;4. 区块链游戏和虚拟资产&#xff1a;5. 数据隐私和安全&#xff1a;6. 去中心化社交媒体&#xff1a;7. 去中心化能源交易&…

通用二进制方式安装Mysql

一、去官网下载MySQL glibc版本 示例环境为CentOS 7.9版本&#xff0c;要安装的Mysql版本为5.7 1.选择版本下载到自己本地 下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 2.将下载的tar包上传到自己的CentOS虚拟主机上 传输完成后&#xff0c;查看确认一下 …

【计算机网络】第 2 课 - 计算机网络的性能指标

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、性能指标 2.1、速率 2.2、带宽 2.3、吞吐量 2.4、时延 2.5、时延带宽积 2.6、往返时间 2.7、利用率 2.8、丢…

【5G PHY】5G控制资源集CORESET介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

组合模式:如何设计实现支持递归遍历的文件系统目录树结构?

组合模式跟我们之前讲的面向对象设计中的“组合关系&#xff08;通过组合来组装两个类&#xff09;”&#xff0c;完全是两码事。这里讲的“组合模式”&#xff0c;主要是用来处理树形结构数据。这里的“数据”&#xff0c;你可以简单理解为一组对象集合&#xff0c;待会我们会…

JVM04-优化JVM内存分配以及内存持续上升问题和CPU过高问题排查

1-JVM内存分配 1.1-JVM内存分配性能问题 JVM内存分配不合理最直接的表现就是频繁的GC&#xff0c;这会导致上下文切换等性能问题&#xff0c;从而降低系统的吞吐量、增加系统的响应时间。因此&#xff0c;如果你在线上环境或性能测试时&#xff0c;发现频繁的GC&#xff0c;且…

Spring异常处理器

文章目录 1. 异常分析2. 异常处理器2.1 异常处理器核心2.2 异常处理顺序 3. 自定义异常 1. 异常分析 问题:   程序允许不免的在各层都可能会产生异常&#xff0c;我们该如何处理这些异常? 如果只是在方法里面单独使用 try… catch… 语句去一个一个的进行捕捉处理的话&#x…