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.rhkb.cn/news/326215.html

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

相关文章

生成ssl证书并配置到nginx

生成ssl证书并配置到nginx 安装证书生成工具 apt-get update apt install software-properties-common add-apt-repository ppa:certbot/certbot apt-get update apt-get install certbot python3-certbot-nginx生成证书 首先在新网上创建一个A链接&#xff0c;域名与服务器做…

vue3 自定义国际化、elementPlus 国际化

自定义国际化 1. 引入 vue-i18n 插件 pnpm install vue-i18nnext 2. 页面添加语言文件目录&#xff0c;添加自定义的语言文件 3.语言目录里添加 index.ts&#xff0c; 内容如下 import { createI18n } from "vue-i18n";// 自定义语言文件 import zhCN from "…

WordPress中插入视频的两种方法详解

最近我在建设WordPress网站的时候需要上传视频&#xff0c;我使用的是Hostease的主机安装的WordPress&#xff0c;随后在咨询了他们的技术支持后获得了一些解决方法。下面将介绍WordPress中插入视频的两种方法&#xff1a;本地上传和外部引用。 本地上传视频 使用WordPress的古…

【eclipse】如何在IDE里创建一个Java Web项目?

如何在eclipse中创建一个动态Web项目并成功运行&#xff1f; 一、 最终效果 懒得写那么多了…我也不知道该怎么写了&#xff0c;有点乱&#xff0c;有问题可以在评论里留言&#xff0c;我看到会解决的&#xff0c;在这个过程中也踩到了一些坑&#xff0c;但好在有CSDN帮助解决…

利用知识图谱提升RAG应用的准确性

文章目录 一、关于 GraphRAG二、Neo4j环境配置三、数据提取四、RAG混合检索1、非结构化数据检索器2、图谱检索器3、最终的检索器 五、定义RAG Chain 本文转载自&#xff1a;lucas大叔 : 利用知识图谱提升RAG应用的准确性 https://zhuanlan.zhihu.com/p/692595027 英文原文&…

网页版五子棋的自动化测试

目录 前言 一、主要技术 二、测试环境的准备部署 三、测试用例 四、执行测试 4.1、公共类设计 创建浏览器驱动对象 测试套件 释放驱动类 4.2、功能测试 登录页面 注册页面 游戏大厅页面 游戏房间页面 测试套件结果 4.3、界面测试 登录页面 注册页面 游戏大…

密码学《图解密码技术》 记录学习 第十五章

目录 十五章 15.1本章学习的内容 15.2 密码技术小结 15.2.1 密码学家的工具箱 15.2.2 密码与认证 15.2.3 密码技术的框架化 15.2.4 密码技术与压缩技术 15.3 虚拟货币——比特币 15.3.1 什么是比特币 15.3.2 P2P 网络 15.3.3地址 15.3.4 钱包 15.3.5 区块链 15.3.…

web安全之登录框渗透骚姿势,新思路

不管漏洞挖掘还是挖SRC&#xff0c;登录框都是重点关注对象&#xff0c;什么漏洞都有可能出现&#xff0c; 本篇文章做个总结&#xff0c;后面发现新思路后会继续更新 万能密码 or 弱口令 SQL注入 水平越权 垂直越权 逻辑漏洞 短信轰炸 邮箱轰炸 信息泄露 验证码DOS XSS万能密…

React:Router-2. createBrowserRouter函数式

参考文档&#xff1a;ReactRouter官网 前边的文章 BrowserRouter组件式路由 提供了组件式路由的方式&#xff0c;在react-router6.4.0及以上版本&#xff0c;提供了 createBrowserRouter 函数式路由创建方式。 一、创建路由 1. 新建router.js文件&#xff0c;使用createBrow…

rac asm新增磁盘报0RA-15333或ORA-15075

虚拟化做的rac&#xff0c;发现原来加盘直接把sdb、sdc、sdd、sde加到asm里了&#xff0c;后面通过udev绑定的盘&#xff0c;增加到asm里就报错&#xff1a; [DBT-30007]Addition of disks to disk group DATA failed ORA-15032:not all alterations performed 0RA-15333: d…

迷宫中离入口最近的出口

题目链接 迷宫中离入口最近的出口 题目描述 注意点 maze[i][j] 要么是 ‘.’ &#xff0c;要么是 ‘’entrance.length 2entrance 一定是空格子出口的含义是 maze 边界上的空格子entrance格子不算出口 解答思路 广度优先遍历找到走i步时所能到达的所有节点位置&#xff0…

idea使用git不提示账号密码登录,而是输入token问题解决

idea 或者 webstream 等全家桶软件 使用git 推送代码时&#xff0c;不提示账号密码登录&#xff0c;而是输入token问题解决 你的代码仓库是gitlab 然后打开修改代码后推送时&#xff0c;会默认使用gitlab插件&#xff0c;所以提示数据token 解决方式就是把gitlab插件取消使用这…

ASP.NET MVC 如何使用 Form Authentication?

前言 .NET 的 Form Authentication 是一种基于表单的简单且灵活的身份验证机制&#xff0c;用户通过输入用户名和密码来登录应用程序&#xff0c;并且通过配置来控制用户访问权限。 在使用 Form Authentication 时&#xff0c;我们需要在 web.config 文件中配置身份验证和授权…

工业级路由器的穿透力是不是更强(原创科普)

今天我想和大家聊聊工业级路由器的一个重要特性——穿透力。作为一名从事工业网络通信的工程师,我发现很多用户在选择工业级路由器时,都会问到一个问题:"工业级路由器的穿透力是不是更强?"下面就让我来为大家解答这个疑问。当然如果有通信产品需要也可以关注星创易联…

导航app为什么知道还有几秒变绿灯?

在使用地图导航app行驶至信号灯的交叉路口时&#xff0c;这些应用程序会贴心地告知用户距信号灯变化还有多少秒&#xff0c;无论是即将转为绿灯还是红灯。这一智能化提示不仅使得驾驶员能适时做好起步或刹车的准备&#xff0c;有效缓解了因等待时间不确定而产生的焦虑情绪&…

如何写好网评文章?写好了怎么去投稿呢,教程来了

如何写好网评文章&#xff0c;可谓仁者见仁、智者见智。俗话说&#xff1a;“冰冻三尺非一日之寒。”写好网评文章决不是一朝一夕能够练成的&#xff0c;是一个漫长的修炼的过程&#xff0c;需要我们耐得住寂寞、静得下心神。从事网评写作六年多&#xff0c;我有一些心得体会和…

LLAMA3中文语料 fine tune 测试与比对

概述&#xff1a; Meta开发并发布了Meta-Lama 3大语言模型家族&#xff08;LLM&#xff09;&#xff0c;Llama 3指令调优模型针对对话用例进行了优化&#xff0c;在常见的行业基准上优于许多可用的开源聊天模型。本文尝试对LLAMA3 在中文语料中尝试进行fine tune 为后续对 通义…

C++ vs Rust vs Go 性能比较

本文对C、Rust和Go三种编程语言编写的gunzip程序进行了性能比较&#xff0c;通过基准测试试图尽可能公平的比较它们的性能。原文: Performance — C vs Rust vs Go 本文将通过一些基准测试&#xff0c;比较 C 和 Rust 以及 Go 编写的相同程序的性能。我们将尽最大努力将语言差异…

Ubuntu20.04右键打不开终端

今天用virtualbox安装了ubuntu20.04 问题&#xff1a;右键打开终端&#xff0c;怎么也打开不了&#xff01; 点了也没反应&#xff0c;或者鼠标转小圈圈&#xff0c;然后也没有反应… 解决方法&#xff1a; 1、Ctrl Alt F6 先切换到终端访问界面 mac电脑 Ctrl Alt F6 …