文章目录

一、MicrometerTracingBrave(Sleuth)链路追踪1、MicrometerTracingBrave和Zipkin的概论2、Docker搭建Zipkin服务3、MicrometerTracingBrave和Zipkin实现链路追踪

二、SkyWaking服务的安装与使用1、SkyWalking的概论2、Java探针的环境搭建3、Java探针实现日志监控4、SkyWalking服务的搭建

三、SpringCloud使用SkyWalking实现链路追踪1、SkyWalking的环境搭建2、SpringCloud项目接入SkyWalking的探针3、Docker搭建Elasticsearch8.7.1环境

总结

一、MicrometerTracingBrave(Sleuth)链路追踪

因为SpringBoot3.0以上移除了Sleuth,迁移到了MicrometerTracingBrave,所以直接使用MicrometerTracingBrave即可。

1、MicrometerTracingBrave和Zipkin的概论

为了能够在分布式架构中快速定位问题,分布式链路追踪应运而生。将一次分布式请求还原成调用链路,进行日志记录,性能监控并将一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等等。 常见的链路追踪技术有Sleuth、Zipkin、pinpoint、skywalking等。SpringCloudSleuth只负责产生监控数据,通过日志的方式展示出来,并没有提供可视化的UI界面。 Sleuth相当于调用链监控工具的客户端,集成在各个微服务上,负责产生调用链监控数据。Sleuth核心概念 1)Span:基本的工作单元,相当于链表中的一个节点,通过一个唯一ID标记它的开始、具体过程和结束。我们可以通过其中存储的开始和结束的时间戳来统计服务调用的耗时。除此之外还可以获取事件的名称、请求信息等。 2)Trace:一系列的Span串联形成的一个树状结构,当请求到达系统的入口时就会创建一个唯一ID(traceId),唯一标识一条链路。这个traceId始终在服务之间传递,直到请求的返回,那么就可以使用这个traceId将整个请求串联起来,形成一条完整的链路。 当调用链经过服务时,会记录TraceID和SpanID以及ParentSpanID。 3)Annotation用来记录具体的事件。 Client Sent,客户端发起一个请求的时间。 Server Received,服务端接收到用户请求并开始处理的时间 Server Sent,服务端将请求处理结果返回给客户端的时间。 Client Received,客户端成功接收到来自服务器响应的时间戳。Zipkin4个核心的组件 1)Collector:收集器组件,它主要用于处理从外部系统发送过来的跟踪信息,将这些信息转换为Zipkin内部处理的 Span 格式,以支持后续的存储、分析、展示等功能。 2)Storage:存储组件,它主要对处理收集器接收到的跟踪信息,默认会将这些信息存储在内存中,我们也可以修改此存储策略,通过使用其他存储组件将跟踪信息存储到数据库中 3)RESTful API:API 组件,它主要用来提供外部访问接口。比如给客户端展示跟踪信息,或是外接系统访问以实现监控等。 4)UI:基于API组件实现的上层应用。通过UI组件用户可以方便而有直观地查询和分析跟踪信息zipkin优点: 1)轻量级 2)使用人数多,成熟zipkin缺点: 1)侵入性 2)功能简单 3)欠缺APM报表能力(能力弱)zipkin致力于收集服务的定时数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。主要作用是收集并查看链路数据。

2、Docker搭建Zipkin服务

在之前安装过RabbitMQ的虚拟机中继续安装Zipkin

下载Zipkin镜像:docker pull openzipkin/zipkin创建并启动Zipkin服务:docker run --name rabbit-zipkin -d -p 9411:9411 --link rabbitmq -e RABBIT_ADDRESSES=rabbitmq:5672 -e RABBIT_USER=guest -e RABBIT_PASSWORD=guest openzipkin/zipkin浏览器访问Zipkin服务:http://192.168.126.11:9411

3、MicrometerTracingBrave和Zipkin实现链路追踪

在gateway9527和payment8001和payment8002以及openfeign-order80项目的POM文件中添加tracing和zipkin依赖。

io.micrometer

micrometer-observation

io.micrometer

micrometer-tracing-bridge-brave

io.github.openfeign

feign-micrometer

12.3

org.springframework.cloud

spring-cloud-starter-stream-rabbit

io.zipkin.reporter2

zipkin-reporter-brave

在gateway9527和payment8001和payment8002以及openfeign-order80项目的yml文件中添加和brave和zipkin的配置信息。 spring:

rabbitmq:

host: 192.168.126.11

port: 5672

username: guest

password: guest

## 设置zipkin和brave配置和tracing的日志信息

logging.pattern.level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]"

management:

zipkin:

tracing:

endpoint: http://192.168.126.11:9411/api/v2/spans

tracing:

sampling:

# 采样率的概率,100%采样

probability: 1.0

gateway9527项目的YML文件配置跳过路由验证和Order的微服务路由 org:

my:

jwt:

# 跳过认证路由

skipAuthUrls:

- /user/login

- /order/index

spring:

application:

#设置应用名

name: cloud-gateway

cloud:

gateway:

# 路由配置

routes:

# 路由ID,没有固定规则但要求唯一,建议配合服务名

- id: cloud-order-consumer

# 匹配后提供服务的路由地址 (即目标服务地址) lb后跟提供服务的微服务的名字

uri: lb://CLOUD-ORDER-CONSUMER

# 断言会接收一个输入参数,返回一个布尔值结果

predicates:

# 路径相匹配的进行路由

- Path=/order/*

测试链路追踪 1)启动Eureka7001和Eureka7002和openfeign-order80和gateway9527和payment8001以及payment8002服务 2)打开Centos7虚拟机,启动RabbitMQ和Zipkin服务 3)在浏览器访问:http://localhost:9527/order/index 请求成功后,在浏览器中打开Zipkin可视化界面:http://192.168.126.11:9411/ 可以看到这时候Zipkin已经存在调用链的链路信息。

二、SkyWaking服务的安装与使用

1、SkyWalking的概论

SkyWalking为服务提供了自动探针代理,将数据通过gRPC或者HTTP传输给后端平台,后端平台将数据存储在Storage中,并且分析数据将结果展示在UI中。SkyWalking的优点 1)多种监控手段多语言自动探针,Java,.NET Core 和 Node.JS 2)轻量高效,不需要大数据 3)模块化,UI、存储、集群管理多种机制可选 4)支持告警 5)社区活跃 6)无代码侵入缺点: 较为新兴,成熟度不够高SkyWalking的功能 SkyWalking提供了非常完善的分布式链路追踪功能 SkyWalking提供了非常完善的错误诊断功能 SkyWalking提供了非常完善的实时链路大屏功能 SkyWalking提供了非常完善的服务拓扑关系分析功能 SkyWalking提供了非常完善的链路指标及错误告警功能 SkyWalking提供了在线性能诊断功能SkyWalking的核心概念 1)宿主应用:探针通过字节码技术引入应用。从探针的视角来看,应用是探针寄生的宿主。 2)探针:收集从应用采集到的链路数据,并将其转换为SkyWalking能够识别的数据格式。 3)RPC:宿主应用和平台后端之间的通信渠道。 4)平台后端:支持数据聚合、分析和流处理,包括跟踪,指标和日志等。 5)存储:通过开放的,可插拔的接口来存储SkyWalking的链路数据。 SkyWalking目前支持 ElasticSearch、H2、MySQL、TiDB、InfluxDB。 6)UI:一个可定制的基于WEB的界面,允许SkyWalking终端用户管理和可视化SkyWalking的链路数据。JavaAgent(Java探针)提供了一种在加载字节码时对字节码进行修改的方式。通常使用ASM Javassist字节码工具修改class文件。 javassist是一个库,实现ClassFileTransformer接口中的transform()方法。ClassFileTransformer 这个接口的目的就是在class被装载到JVM之前将class字节码转换掉,从而达到动态注入代码的目的。Java探针工具技术原理 1)在JVM加载class二进制文件的时候,利用ASM动态的修改加载的class文件,在监控的方法前后添加计时器功能,用于计算监控方法耗时; 2)将监控的相关方法 和 耗时及内部调用情况,按照顺序放入处理器; 3)处理器利用栈先进后出的特点对方法调用先后顺序做处理,当一个请求处理结束后,将耗时方法轨迹和入参map输出到文件中; 4)然后区分出耗时的业务,转化为xml格式进行解析和分析。 即将.class文件进行修改,添加计时器功能;将监控方法的耗时及调用情况放入处理器;将后面的调用方法出栈后,将当前调用方法时间减去前面调用方法时间即可拿到耗时和获取轨迹;通过以上的数据进行分析,即可区分耗时数据。Java探针工具的功能 1)支持方法执行耗时范围抓取设置,根据耗时范围抓取系统运行时出现在设置耗时范围的代码运行轨迹。 2)支持抓取特定的代码配置,方便对配置的特定方法进行抓取,过滤出关系的代码执行耗时情况。 3)支持APP层入口方法过滤,配置入口运行前的方法进行监控,相当于监控特有的方法耗时,进行方法专题分析。 4)支持入口方法参数输出功能,方便跟踪耗时高的时候对应的入参数。 5)提供WEB页面展示接口耗时展示、代码调用关系图展示、方法耗时百分比展示、可疑方法凸显功能。

2、Java探针的环境搭建

创建helloagent项目 在helloagent项目的POM文件中添加如下依赖

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

3.0.5

com.zzx

helloagent

0.0.1-SNAPSHOT

17

org.springframework.boot

spring-boot-starter

org.projectlombok

lombok

true

org.springframework.boot

spring-boot-starter-test

test

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-maven-plugin

在com.zzx.controller包下创建HelloController类,代码如下 package com.zzx.controller;

import lombok.extern.slf4j.Slf4j;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

@Slf4j

public class HelloController {

@GetMapping("/hello")

public String hello() {

return "hello JavaAgent";

}

}

启动helloagent项目后,在浏览器访问:localhost:8080/hello 对helloagent项目进行打包,即先打开maven的窗口,然后找到下图的packeage双击,等待打包,出现Success即打包成功。 打完包后,在target目录中会有一个以项目命名的 jar包文件以及控制台出现Success。 因为项目下target目录在项目没有显示,此时可以在项目的文件夹中去找 打开项目文件夹下的target文件夹,将打包后的jar包复制到一个文件夹中。

3、Java探针实现日志监控

创建javaagent项目 在javaagent项目的POM文件中添加如下依赖

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

com.zzx

javaagent

1.0-SNAPSHOT

17

17

org.javassist

javassist

3.29.2-GA

javaagent

org.apache.maven.plugins

maven-shade-plugin

3.0.0

package

shade

implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">

com.zzx.TestAgent

在javaagent项目的com.zzx包下,创建修改.class文件的探针实现类TestTransformer ,代码如下 package com.zzx;

import javassist.*;

import java.io.IOException;

import java.lang.instrument.ClassFileTransformer;

import java.lang.instrument.IllegalClassFormatException;

import java.security.ProtectionDomain;

public class TestTransformer implements ClassFileTransformer {

private final String CLASS_NAME = "com.zzx.controller.HelloController";

private final String METHOD_NAME = "hello";

@Override

public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

// 1.获取类名字

String name = className.replace("/",".");

// 2.判断是否是我要修改的类

if(name.equals(CLASS_NAME)){

// 3.javassist是一个处理java字节码的类库

//java字节码存储在一个class file的二进制文件里

//每个class文件包含一个java类或接口

//java ssist.ctclass 就是class文件的抽象表示

CtClass ctClass;

try {

// 4.获取helloController类搜索路径

ctClass = ClassPool.getDefault().get(name);

System.out.println("CtClass is OK");

// 5.获取类中的方法

CtMethod method = ctClass.getDeclaredMethod(METHOD_NAME);

System.out.println("CtMethod is OK");

method.insertBefore("System.out.println(\"字节码添加成功,打印日志\");");

return ctClass.toBytecode();

} catch (NotFoundException e) {

e.printStackTrace();

} catch (CannotCompileException e) {

e.printStackTrace();

} catch (IOException e) {

throw new RuntimeException(e);

}

}

return null;

}

}

在javaagent项目的com.zzx包下,创建探针类TestAgent,代码如下 package com.zzx;

import java.lang.instrument.Instrumentation;

/**

* 探针类

*/

public class TestAgent {

/**

* 在main方法运行前,与main方法运行于同一JVM中

*

* @param agentArgs agentArgs是premain函数得到的程序参数,随同"-javaagent"一同传入,

* 与main函数不同的是,该参数是一个字符串而不是一个字符串数组,

* 如果程序参数有多个,程序将自行解析这个字符串

* @param inst 一个java.lang.instrument.Instrumentation实例,由JVM自动传入,

* java.lang.instrument.Instrumentation是instrument包中的一个接口,

* 也是核心部分,集中了其中几乎所有的功能方法,例如类定义的转换和操作

*/

public static void premain(String agentArgs, Instrumentation inst){

System.out.println("********* premain 执行了 **********");

System.out.println("agentArgs:"+agentArgs);

inst.addTransformer(new TestTransformer());

}

}

将实现探针功能的类javaagent进行打包 因为项目下target目录在项目没有显示,此时可以在项目的文件夹中去找 打开项目文件夹下的target文件夹,复制下面的第一个jar包到刚刚存放helloagent.jar的文件夹下。 在存放两个jar包的文件夹的目录那里,输入cmd回车,进入命令行。 测试探针 1)进入命令行后,输入:java -javaagent:javaagent.jar -jar helloagent-0.0.1-SNAPSHOT.jar 2)在浏览器中访问:localhost:8080/hello 即在访问后,会打印字节码添加成功,打印日志这个字符串。代表JAVA探针修改.class文件成功。

4、SkyWalking服务的搭建

下载9.4.0版本的SkyWalking:https://dlcdn.apache.org/skywalking/9.4.0/apache-skywalking-apm-9.4.0.tar.gz 使用mobax上传功能,将Linux版本的JDK和SkyWalking上传到opt目录下 在opt目录中,输入将JDK解压到/usr/local的命令:tar -zxvf jdk-11.0.15.1_linux-x64_bin.tar.gz -C /usr/local/ 进入到/usr/local目录下,获取JDK名字,再编辑profile文件:vim /etc/profile,在文件底部添加如下配置: export JAVA_HOME=/usr/local/jdk-11.0.15.1

export PATH=$PATH:$JAVA_HOME/bin

生效profile文件:source /etc/profile查看jdk的版本号:java -version 到opt目录下,在命令行中输入命令解压SkyWalking到/usr/local目录中:tar -zxvf apache-skywalking-apm-9.4.0.tar.gz -C /usr/local/ SkyWalking解压后的目录:

webapp: Ul前端(web 监控页面)的jar包和配置文件oap-libs:后台应用的jar包,以及它的依赖jar包config:启动后台应用程序的配置文件,是使用的各种配置bin:各种启动脚本,一般使用脚本startup.*来启动web页面和对应的后台应用agent:代理服务jar包 修改web的yml文件的端口号信息:vim /usr/local/apache-skywalking-apm-bin/webapp/application.yml 启动SkyWalking服务

到bin目录下:cd /usr/local/apache-skywalking-apm-bin/bin启动SkyWalking:./startup.sh 在浏览器中访问:http://192.168.126.11:8068/

三、SpringCloud使用SkyWalking实现链路追踪

1、SkyWalking的环境搭建

在体验完Java探针后,打开之前的cloud项目,复制cloud-consumer-openfeign-order80,粘贴到cloud父工程中,并修改名字为cloud-consumer-openfeign-skywalking-order80 修改cloud-consumer-openfeign-skywalking-order80项目的POM文件的项目名 在cloud父工程的POM文件中手动添加该子项目 修改主启动类的名字 移除cloud-consumer-openfeign-skywalking-order80项目的POM文件中之前的brave和zipkin的依赖 此时再复制cloud-provider-payment8001项目,粘贴到cloud父项目中,改名字为cloud-provider-skywalking-payment8001 跟上面的cloud-consumer-openfeign-skywalking-order80修改步骤相同。 最后,在cloud-consumer-openfeign-skywalking-order80项目的YML文件中添加如下配置 spring:

main:

#允许存在多个Feign调用相同Service的接口

allow-bean-definition-overriding: true

即允许多个接口使用@FeignClient调用同一个服务。

2、SpringCloud项目接入SkyWalking的探针

下载JavaAgent:https://dlcdn.apache.org/skywalking/java-agent/8.15.0/apache-skywalking-java-agent-8.15.0.tgz 直接在文件夹中解压JavaAgent到当前文件即可,然后剪切该文件夹到cloud父工程即可。 编辑两个SkyWalking项目Configuration 编辑SkyWalkingOrderFeignMain80项目Configuration的VM options,代码如下 -javaagent:D:\CODE\IDEA\cloud\skywalking-agent\skywalking-agent.jar

-DSW_AGENT_NAME=consumer-order

-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.126.11:11800

编辑SkyWalkingPaymentMain8001项目Configuration的VM options,代码如下 -javaagent:D:\CODE\IDEA\cloud\skywalking-agent\skywalking-agent.jar

-DSW_AGENT_NAME=provider-payment

-DSW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.126.11:11800

此时-DSW_AGENT_NAME是指服务名字(自定义),只需要保证唯一性即可。

测试 1)启动Eureka7001和Eureka7002和SkyWalking的服务提供者和消费者 2)在浏览器访问:192.168.126.11:8068

3、Docker搭建Elasticsearch8.7.1环境

下载elasticsearch:docker pull elasticsearch:8.7.1 创建并启动Elasticsearch:docker run --restart=always -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms512m -Xmx512m" --name='es' -d elasticsearch:8.7.1

-d:守护进程运行ES_JAVA_OPTS:设置堆内存discovery.type:设置单节点启动 拷贝docker下的es容器的elasticsearch.yml文件:docker cp es:/usr/share/elasticsearch/config/elasticsearch.yml . 修改拷贝到当前目录下的elasticsearch.yml文件:vim elasticsearch.yml,配置如下 cluster.name: "docker-cluster"

network.host: 0.0.0.0

#----------------------- BEGIN SECURITY AUTO CONFIGURATION -----------------------

#

# The following settings, TLS certificates, and keys have been automatically

# generated to configure Elasticsearch security features on 10-05-2023 15:57:14

#

# --------------------------------------------------------------------------------

# Enable security features

xpack.security.enabled: false

xpack.security.enrollment.enabled: false

# Enable encryption for HTTP API client connections, such as Kibana, Logstash, and Agents

xpack.security.http.ssl:

enabled: false

keystore.path: certs/http.p12

# Enable encryption and mutual authentication between cluster nodes

xpack.security.transport.ssl:

enabled: false

verification_mode: certificate

keystore.path: certs/transport.p12

truststore.path: certs/transport.p12

#----------------------- END SECURITY AUTO CONFIGURATION -------------------------

将修改的elasticsearch.yml文件拷贝到es容器下存放elasticsearch.yml的目录下:docker cp elasticsearch.yml es:/usr/share/elasticsearch/config/ 重启ES服务:docker restart es 在浏览器上访问ES服务:192.168.126.11:9200

总结

因为SpringBoot3.0以上移除了Sleuth,迁移到了MicrometerTracingBrave,所以直接使用MicrometerTracingBrave即可。 1)MicrometerTracing组件主要解决链路追踪的问题。 MicrometerTracingBrave只负责产生监控数据,通过日志的方式展示出来,并没有提供可视化的UI界面。 MicrometerTracingBrave核心概念,有Span、Trace、Annotation。Span是微服务调用链的节点;Brave是微服务调用链的入口节点;Annotation是微服务调用链用来记录具体事件的。 2)实现MicrometerTracingBrave的链路追踪,需要在使用的微服务项目中导入Brave和Zipkin依赖、在YML文件中配置Brave和Zipkin,配置Brave的采样率和日志等级以及rabbimq等配置信息。而且需要使用虚拟机,安装rabbitmq和zipkin服务。1)zipkin稳定,但是功能简单,入侵性强;但是SkyWalking功能强,但是不够稳定,无代码入侵。 SkyWalking的主要作用是链路追踪。 2)JavaAgent(Java探针)提供了一种在加载字节码时对字节码进行修改的方式。 即将.class文件进行修改,添加计时器功能;将监控方法的耗时及调用情况放入处理器;将后面的调用方法出栈后,将当前调用方法时间减去前面调用方法时间即可拿到耗时和获取轨迹;通过以上的数据进行分析,即可区分耗时数据。 3)Java探针的使用,需要在实现探针的项目的POM文件中导入javassist依赖,也就是能处理java字节码的类库依赖,并且需要指定Premain类的路径,也就是在premain方法的类的路径。 需要将原先的项目打成jar包;然后该编写探针类,获取需要修改的类或类的方法,进行修改.class文件。 在命令行中使用指定的探针语法即可启动项目并且实现无侵入修改原先的项目的功能。SpringCloud使用SkyWalking实现分布式链路追踪,首先需要去官网下载SkyWalking的压缩包,在Linux虚拟机中进行安装部署SkyWalking服务;再去官网下载JavaAgent压缩包,解压即可使用;在需要进行调用链的链路追踪的项目中进行Edit Configuration,然后进行指定JavaAgent的路径和自定义服务名(确保唯一)以及指定Agent的连接地址跟端口。然后即可在浏览器中打开SkyWalking的界面。1)SkyWalking官方推荐使用ElasticSearch; 2)使用docker快速搭建Elasticsearch,安装并启动docker,然后拉取Elasticsearch镜像,然后启动ES,修改配置文件即可使用。

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: