4. 分布式链路追踪客户端工具包Starter设计

前言

本文将从零搭建分布式链路追踪客户端工具包的Starter,并将在后续文章中逐步丰富支持的场景。这里首先将搭建一个最基础的Starter,能提供的功能和1. 看完这篇文章我奶奶都懂Opentracing了一文中的示例demo类似。

相关版本依赖如下。

opentracing-api版本:0.33.0
opentracing-spring-web版本:4.1.0
jaeger-client版本:1.8.1
Springboot版本:2.7.6

github地址:honey-tracing

正文

一. 基础Starter实现

在基础Starter中,主要是提供Servlet过滤器RestTemplate拦截器,我们后续的复杂功能,就将在这个基础Starter上一点一点的丰富。

首先下图是Starter的工程结构。

在基础Starter中,Servlet的链路过滤器实现如下。

public class HoneyTracingFilter implements Filter {private final Tracer tracer;public HoneyTracingFilter(Tracer tracer) {this.tracer = tracer;}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;SpanContext extractedSpanContext = tracer.extract(Format.Builtin.HTTP_HEADERS,new HttpServletRequestExtractAdapter(request));Span span = tracer.buildSpan(request.getMethod()).asChildOf(extractedSpanContext).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER).start();try (Scope scope = tracer.activateSpan(span)) {filterChain.doFilter(servletRequest, servletResponse);} catch (IOException | ServletException e) {Tags.ERROR.set(span, Boolean.TRUE);throw e;} finally {span.finish();}}}

RestTemplate的链路拦截器实现如下。

* RestTemplate客户端的分布式链路追踪拦截器。*/
public class HoneyRestTemplateTracingInterceptor implements ClientHttpRequestInterceptor {private final Tracer tracer;public HoneyRestTemplateTracingInterceptor(Tracer tracer) {this.tracer = tracer;}@NotNullpublic ClientHttpResponse intercept(@NotNull HttpRequest request, @NotNull byte[] body,ClientHttpRequestExecution execution) throws IOException {Span span = tracer.buildSpan(HONEY_REST_TEMPLATE_NAME).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).start();tracer.inject(span.context(), Format.Builtin.HTTP_HEADERS, new HttpHeadersCarrier(request.getHeaders()));try (Scope scope = tracer.activateSpan(span)) {return execution.execute(request, body);} catch (IOException e) {Tags.ERROR.set(span, Boolean.TRUE);throw e;} finally {span.finish();}}}

打印链路日志的HoneySpanReporter目前不打印任何日志,后面再添加打印逻辑,实现如下。

public class HoneySpanReporter implements Reporter {public void report(JaegerSpan span) {}public void close() {}}

我们使用HoneyTracingProperties来读取链路相关的配置,目前仅读取一个开关enabled,如下所示。

* 分布式链路追踪配置属性类。*/
@ConfigurationProperties("honey.tracing")
public class HoneyTracingProperties {private boolean enabled;public boolean isEnabled() {return enabled;}public void setEnabled(boolean enabled) {this.enabled = enabled;}}

使用到的一些常量,存放在CommonConstants中,如下所示。

public class CommonConstants {public static final double DEFAULT_SAMPLE_RATE = 1.0;public static final String HONEY_TRACER_NAME = "HoneyTracer";public static final String HONEY_REST_TEMPLATE_NAME = "HoneyRestTemplate";public static final String ALL_URL_PATTERN_STR = "/*";}

再接下来就是三个自动装配类,其中HoneyRestTemplateTracingConfig负责注册HoneyRestTemplateTracingInterceptor给容器中所有的RestTemplateHoneyTracingConfig负责注册TracerSpring容器,HoneyTracingFilterConfig负责注册HoneyTracingFilter,实现如下所示。

* RestTemplate分布式链路追踪配置类。*/
@ConditionalOnBean(RestTemplate.class)
@Configuration
@AutoConfigureAfter(HoneyTracingConfig.class)
public class HoneyRestTemplateTracingConfig {public HoneyRestTemplateTracingConfig(List<RestTemplate> restTemplates, Tracer tracer) {for (RestTemplate restTemplate : restTemplates) {restTemplate.getInterceptors().add(new HoneyRestTemplateTracingInterceptor(tracer));}}}
* 分布式链路追踪配置类。*/
@Configuration
@EnableConfigurationProperties({HoneyTracingProperties.class})
@ConditionalOnProperty(prefix = "honey.tracing", name = "enabled", havingValue = "true", matchIfMissing = true)
public class HoneyTracingConfig {@Bean@ConditionalOnMissingBean(Sampler.class)public Sampler sampler() {return new ProbabilisticSampler(DEFAULT_SAMPLE_RATE);}@Bean@ConditionalOnMissingBean(Reporter.class)public Reporter reporter() {return new HoneySpanReporter();}@Bean@ConditionalOnMissingBean(Tracer.class)public Tracer tracer(Sampler sampler, Reporter reporter) {return new JaegerTracer.Builder(HONEY_TRACER_NAME).withTraceId128Bit().withZipkinSharedRpcSpan().withSampler(sampler).withReporter(reporter).build();}}
* Servlet过滤器配置类。*/
@Configuration
@AutoConfigureAfter(HoneyTracingConfig.class)
public class HoneyTracingFilterConfig {@Beanpublic FilterRegistrationBean<HoneyTracingFilter> honeyTracingFilter(Tracer tracer) {HoneyTracingFilter honeyTracingFilter = new HoneyTracingFilter(tracer);FilterRegistrationBean<HoneyTracingFilter> filterFilterRegistrationBean= new FilterRegistrationBean<>(honeyTracingFilter);filterFilterRegistrationBean.addUrlPatterns(ALL_URL_PATTERN_STR);return filterFilterRegistrationBean;}}

最后就是spring.factoriespom文件,内容如下所示。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.honey.tracing.config.HoneyTracingConfig,\com.honey.tracing.config.HoneyTracingFilterConfig,\com.honey.tracing.config.HoneyRestTemplateTracingConfig
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>honey-tracing</artifactId><groupId>com.honey</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>honey-starter-tracing</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId></dependency><dependency><groupId>io.opentracing</groupId><artifactId>opentracing-api</artifactId><scope>provided</scope></dependency><dependency><groupId>io.opentracing.contrib</groupId><artifactId>opentracing-spring-web</artifactId><scope>provided</scope></dependency><dependency><groupId>io.jaegertracing</groupId><artifactId>jaeger-client</artifactId><scope>provided</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><executions><execution><id>attach-sources</id><goals><goal>jar</goal></goals></execution></executions></plugin></plugins></build></project>

还有一点要补充,父工程的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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><packaging>pom</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.6</version></parent><groupId>com.honey</groupId><artifactId>honey-tracing</artifactId><version>1.0-SNAPSHOT</version><dependencyManagement><dependencies><dependency><groupId>io.opentracing</groupId><artifactId>opentracing-api</artifactId><version>0.33.0</version></dependency><dependency><groupId>io.opentracing.contrib</groupId><artifactId>opentracing-spring-web</artifactId><version>4.1.0</version></dependency><dependency><groupId>io.jaegertracing</groupId><artifactId>jaeger-client</artifactId><version>1.8.1</version></dependency></dependencies></dependencyManagement><modules><module>honey-starter-tracing</module><module>honey-tracing-example</module></modules></project>

二. 测试demo搭建

我们需要一个demo来测试我们的基础Starter,并且随着后续Starter支持的功能的增多,我们的demo也要相应的扩展更多的场景。

首先是demo的目录结构,如下所示。

1. example-service-1

RestTemplateConfig简单的向Spring容器注册了一个RestTemplatebean,如下所示。

@Configuration
public class RestTemplateConfig {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}}

RestTemplateController提供了发送接口,如下所示。

@RestController
public class RestTemplateController {@Autowiredprivate RestTemplate restTemplate;@GetMapping("/send")public void send(String url) {restTemplate.getForEntity(url, Void.class);}}

最后是application.ymlpom文件,如下所示。

server:port: 8080
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>honey-tracing-example</artifactId><groupId>com.honey</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>example-service-1</artifactId><dependencies><dependency><groupId>com.honey</groupId><artifactId>honey-starter-tracing</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>io.opentracing</groupId><artifactId>opentracing-api</artifactId><version>0.33.0</version></dependency><dependency><groupId>io.opentracing.contrib</groupId><artifactId>opentracing-spring-web</artifactId><version>4.1.0</version></dependency><dependency><groupId>io.jaegertracing</groupId><artifactId>jaeger-client</artifactId><version>1.8.1</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>
2. example-service-2

RestTemplateController提供了接收接口,如下所示。

@RestController
public class RestTemplateController {@GetMapping("/receive")public void receive() {System.out.println();}}

最后是application.ymlpom文件,如下所示。

server:port: 8081
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>honey-tracing-example</artifactId><groupId>com.honey</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>example-service-2</artifactId><dependencies><dependency><groupId>com.honey</groupId><artifactId>honey-starter-tracing</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>io.opentracing</groupId><artifactId>opentracing-api</artifactId><version>0.33.0</version></dependency><dependency><groupId>io.opentracing.contrib</groupId><artifactId>opentracing-spring-web</artifactId><version>4.1.0</version></dependency><dependency><groupId>io.jaegertracing</groupId><artifactId>jaeger-client</artifactId><version>1.8.1</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>

总结

在本文,首先实现了一个基础的Starter包,为分布式链路追踪提供了Servlet过滤器和RestTemplate拦截器,其次实现了一个demo,后续分布式链路追踪Starter的功能,将用该demo完成测试。
原文:https://juejin.cn/post/7337216565097562149

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

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

相关文章

Scala学习2: 控制结构和函数

目录 第二章 控制结构和函数1- 条件表达式2- 语句终止3- 块表达式和赋值4- 输入和输出5- 循环6- 高级for循环和for推到式7- 函数8- 默认参数和带名参数9- 可变参数10- 过程11- 懒值12- 异常end 第二章 控制结构和函数 1- 条件表达式 Scala的 if/esle 语法结构与java一样, 但是…

MySQL表突然卡死,删、查操作加载不停解决办法

今天遇到了MySQL删表的时候卡死情况。然后通过网上查阅资料和项目组沟通&#xff0c;了解到了有多人同时对同一张表进行了操作。我和另一个同事同时进行了删除操作&#xff0c;然后另两位同时进行了查询操作&#xff0c;然后还有一位同事用dolphin调度&#xff0c;用datax采集数…

【SQL】SQL常见面试题总结(4)

目录 1、空值处理1.1、统计有未完成状态的试卷的未完成数和未完成率1.2、0 级用户高难度试卷的平均用时和平均得分 2、高级条件语句2.1、筛选限定昵称成就值活跃日期的用户&#xff08;较难&#xff09;2.2、筛选昵称规则和试卷规则的作答记录&#xff08;较难&#xff09;2.3、…

SmartEDA助力电工基础实验:打造高效、智能的学习新体验

在电工基础实验的教学与学习中&#xff0c;传统的实验设备往往存在着操作复杂、数据处理繁琐等问题&#xff0c;给学生的学习带来了不小的挑战。然而&#xff0c;随着科技的不断发展&#xff0c;一种名为SmartEDA的智能电工实验辅助设备正逐渐走入课堂&#xff0c;以其高效、智…

Es6-对象新增了哪些扩展?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Javascript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来Javascript篇专栏内容:Es6-对象新增了哪些扩展&#xff1f; 目录 一、参数 二、属性 函数的length属性 …

Unsupervised Out-of-Distribution Detection with Diffusion Inpainting

Unsupervised Out-of-Distribution Detection with Diffusion Inpainting 摘要1.介绍2 背景3 3. Lift, Map, Detect摘要 无监督的异常分布检测(OOD)旨在通过仅从未标记的域内数据中学习来识别域外数据。我们提出了一种用于此任务的新方法——提升、映射、检测(LMD),该方法…

数据结构-栈(带图)

目录 栈的概念 画图理解栈 栈的实现 fun.h fun.c main.c 栈的概念 栈&#xff08;Stack&#xff09;是一种基本的数据结构&#xff0c;其特点是只允许在同一端进行插入和删除操作&#xff0c;这一端被称为栈顶。遵循后进先出&#xff08;Last In, First Out, LIFO&#…

浏览器下载附件流建议

大文件下载可采用附件流的方式&#xff0c;后端设置一下响应参数&#xff0c;然后以流的方式返回前端 res.set({ "Content-Type": "application/octet-stream", "Content-Disposition": "attachment;filename* UTF-8"fixedEncodeUR…

【论文粗读|arXiv】GaSpCT: Gaussian Splatting for Novel CT Projection View Synthesis

Abstract 本文提出了一种新颖的视图合成和3D场景表示方法&#xff0c;用于为计算机断层扫描&#xff08;CT&#xff09;生成新的投影视图。 方法采用了Gaussian Splatting 框架&#xff0c;基于有限的2D图像投影集&#xff0c;无需运动结构&#xff08;SfM&#xff09;方法&am…

CSPM-4是什么?报考条件有哪些?

2021年10月&#xff0c;《国家标准化发展纲要》明确提出构建多层次从业人员培养培训体系&#xff0c;开展专业人才培养培训和国家质量基础设施综合教育。建立健全人才的职业能力评价和激励机制。由中国标准化协会&#xff08;CAS&#xff09;组织开展的项目管理专业人员能力评价…

Swift 5.9 中 if 与 switch 语句简洁新语法让撸码更带劲

概览 在实际代码开发中&#xff0c;可能初学 Swift 语言的小伙伴们在撸码时最常用的得数 if 和 switch…case 条件选择语句了。不过在某些场景下它们显得略有那么一丢丢“矫揉造作”&#xff0c;还好从 Swift 5.9 开始苹果知趣的为其简化了语法且增强了它们的表现力。 在本篇…

Vitis HLS 学习笔记--优化本地存储器访问瓶颈

目录 1. 简介 2. 代码解析 2.1 原始代码 2.2 优化后 2.3 分析优化措施 3. 总结 1. 简介 在Vitis HLS中&#xff0c;实现II&#xff08;迭代间隔&#xff09; 1是提高循环执行效率的关键。II1意味着每个时钟周期都可以开始一个新的迭代&#xff0c;这是最理想的情况&…

Java实现音频转文本(语音识别)

在Java中实现音频转文本&#xff08;也称为语音识别或ASR&#xff09;通常涉及使用专门的语音识别服务&#xff0c;如Google Cloud Speech-to-Text、IBM Watson Speech to Text、Amazon Transcribe、Microsoft Azure Speech Services&#xff0c;或者一些开源库如CMU Sphinx。 …

2024年第四届长三角高校数学建模竞赛C题思路

赛道C:汽后配件需求预测问题 在汽后行业的供应链管理中, 精准的需求预测是后续管理及决策的基础。 各个汽后配件即为一个库存单位(SKU, Stock Keeping Unit), 如果可以准确预知未来对于各个配件的市场需求, 就可以提前将库存放在靠近需求的仓库中, 从而降低库存成本,…

HNCTF ——baby_python

H&NCTF 2024 官方WP (qq.com) OpCodes Pickle.jl (juliahub.com) nc之后 PS D:\ForCode\pythoncode\.idea> nc hnctf.yuanshen.life 33267 # Python 3.10.12 from pickle import loads main b"\x80\x04ctypes\nFunctionType\n(ctypes\nCodeType\n(I1\nI0\nI0\n…

[Linux] 常用服务器命令(持续更新)

文件操作 # 显示文件系统的磁盘空间使用情况 df -h全局查找文件 find / -type f -iname "java"find / -name libncurses*拷贝整个文件夹 cp -r /home/a/ /home/b/ 解压&#xff0c;撤销解压 撤销zip解压 zipinfo -1 path/xx.zip | xargs rm -rf 撤销tar解压 tar …

【Vim】

一、什么是Vim&#xff1f; Vim 是一个历史悠久的文本编辑器&#xff0c;可以追溯到 qed。 Bram Moolenaar 于 1991 年发布初始版本。Vim 有着悠久的历史;它起源于 Vi 编辑器&#xff08;1976 年&#xff09;&#xff0c;至今仍在开发中。(Vim has a rich history; it origina…

css+html 爱心❤

效果 代码实现 html <div class"main"><div class"aixin"></div></div>css .main {transform: rotate(-45deg);}.aixin {height: 100px;width: 100px;background-color: red;margin: auto;margin-top: 200px;position: relativ…

MySQL第一次作业(基本操作)

目录 一、登陆数据库 二、创建数据库zoo 三、修改数据库zoo字符集为gbk 四、选择当前数据库为zoo 五、查看创建数据库zoo信息 六、删除数据库zoo 一、登陆数据库 指令&#xff1a; mysql -u root -p 二、创建数据库zoo 指令&#xff1a; create database zoo; 三、修改数…

基于PHP+MySQL组合开发的多用户自定义商城系统源码 附带源代码包以及搭建教程

系统概述 互联网技术的飞速发展&#xff0c;电子商务已成为人们日常生活中不可或缺的一部分。商城系统作为电子商务的核心&#xff0c;其开发技术和用户体验直接影响着电商平台的竞争力和用户满意度。本文旨在介绍一个基于PHPMySQL组合开发的多用户自定义商城系统&#xff0c;…