看完这篇文章我奶奶都懂Opentracing了 (三)

三. 扩展点分析

通过前面的分析我们了解到,Opentracing对分布式链路追踪中的各种概念进行了统一的定义,某种程度上,已经成为分布式链路追踪的规范。

Java语言中,Opentracing定义了诸如SpanTracer等概念对应的接口,不同的分布式链路实现方需要结合具体的实现方案来提供相应实现,例如本文选择的Jaeger,其提供的JaegerSpan实现了Span接口,JaegerTracer实现了Tracer接口等。

现在接口定义已经有了,具体的实现也有了,该怎么用起来呢。在本文的示例中,具体的使用案例就是我们提供的RestTemplate拦截器,以及过滤器TracingFilter,那么问题就来了,为什么我知道可以这么用,是因为我比较聪明吗,那必然不是,当然是Opentracing告诉我该这么用,所以我才这么用,既然Opentracing定义好了接口,还告诉了用户该怎么用,那么有没有一种可能,Opentracing来提供RestTemplate拦截器,来提供过滤器TracingFilter呢,那完全是有可能的,Opentracing也正是这么做的。

OpentracingRestTemplate提供了一个拦截器叫做TracingRestTemplateInterceptor,也提供了一个过滤器叫做TracingFilter,好吧,到这里我就不装了,示例中的RestTemplate拦截器和过滤器TracingFilter,其实就是抄的Opentracing的,不过我没抄全,毕竟我只是需要搭建一个演示demo,所以官方的很多为了提升扩展性的扩展点,我都给砍掉了,而这些扩展点,正是我们基于已有的轮子造更好的轮子的基础,也正是本节的分析重点。

1. ServletFilterSpanDecorator和RestTemplateSpanDecorator

我们先看一下io.opentracing.contrib.web.servlet.filter.TracingFilter中有哪些扩展点。OpentracingServlet提供了一个专门服务于分布式链路追踪的过滤器TracingFilter,其实现了javax.servlet.Filter接口,关键的doFilter() 方法如下所示。

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;if (!isTraced(httpRequest, httpResponse)) {chain.doFilter(httpRequest, httpResponse);return;}if (servletRequest.getAttribute(SERVER_SPAN_CONTEXT) != null) {chain.doFilter(servletRequest, servletResponse);} else {SpanContext extractedContext = tracer.extract(Format.Builtin.HTTP_HEADERS,new HttpServletRequestExtractAdapter(httpRequest));final Span span = tracer.buildSpan(httpRequest.getMethod()).asChildOf(extractedContext).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER).start();httpRequest.setAttribute(SERVER_SPAN_CONTEXT, span.context());for (ServletFilterSpanDecorator spanDecorator: spanDecorators) {spanDecorator.onRequest(httpRequest, span);}try (Scope scope = tracer.activateSpan(span)) {chain.doFilter(servletRequest, servletResponse);if (!httpRequest.isAsyncStarted()) {for (ServletFilterSpanDecorator spanDecorator : spanDecorators) {spanDecorator.onResponse(httpRequest, httpResponse, span);}}} catch (Throwable ex) {for (ServletFilterSpanDecorator spanDecorator : spanDecorators) {spanDecorator.onError(httpRequest, httpResponse, ex, span);}throw ex;} finally {if (httpRequest.isAsyncStarted()) {httpRequest.getAsyncContext().addListener(new AsyncListener() {@Overridepublic void onComplete(AsyncEvent event) throws IOException {HttpServletRequest httpRequest = (HttpServletRequest) event.getSuppliedRequest();HttpServletResponse httpResponse = (HttpServletResponse) event.getSuppliedResponse();for (ServletFilterSpanDecorator spanDecorator: spanDecorators) {spanDecorator.onResponse(httpRequest,httpResponse,span);}span.finish();}@Overridepublic void onTimeout(AsyncEvent event) throws IOException {HttpServletRequest httpRequest = (HttpServletRequest) event.getSuppliedRequest();HttpServletResponse httpResponse = (HttpServletResponse) event.getSuppliedResponse();for (ServletFilterSpanDecorator spanDecorator : spanDecorators) {spanDecorator.onTimeout(httpRequest,httpResponse,event.getAsyncContext().getTimeout(),span);}}@Overridepublic void onError(AsyncEvent event) throws IOException {HttpServletRequest httpRequest = (HttpServletRequest) event.getSuppliedRequest();HttpServletResponse httpResponse = (HttpServletResponse) event.getSuppliedResponse();for (ServletFilterSpanDecorator spanDecorator: spanDecorators) {spanDecorator.onError(httpRequest,httpResponse,event.getThrowable(),span);}}@Overridepublic void onStartAsync(AsyncEvent event) throws IOException {}});} else {span.finish();}}}
}

通过上述代码,可以发现有一个满脸长着我是扩展点的东西,就是ServletFilterSpanDecorator,其主要负责在过滤器链执行之前,之后以及发生异常时对Span进行装饰,怎么理解这里的装饰呢,其实就是往Span添加一些东西或者修改一些东西,举个例,在过滤器链执行前,往SpanTags中添加本次请求的URI,然后在过滤器链执行后,往SpanTags中添加本次请求的响应码,等等这些需求,都可以在ServletFilterSpanDecorator中完成,这其实就赋予了我们对Span极高的可操作性。

装饰器除了在TracingFilter中有被使用,同样也在Opentracing提供的TracingRestTemplateInterceptor中被使用,其intercept() 方法如下所示。

@Override
public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] body,ClientHttpRequestExecution execution) throws IOException {ClientHttpResponse httpResponse;Span span = tracer.buildSpan(httpRequest.getMethod().toString()).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).start();tracer.inject(span.context(), Format.Builtin.HTTP_HEADERS,new HttpHeadersCarrier(httpRequest.getHeaders()));for (RestTemplateSpanDecorator spanDecorator : spanDecorators) {try {spanDecorator.onRequest(httpRequest, span);} catch (RuntimeException exDecorator) {log.error("Exception during decorating span", exDecorator);}}try (Scope scope = tracer.activateSpan(span)) {httpResponse = execution.execute(httpRequest, body);for (RestTemplateSpanDecorator spanDecorator : spanDecorators) {try {spanDecorator.onResponse(httpRequest, httpResponse, span);} catch (RuntimeException exDecorator) {log.error("Exception during decorating span", exDecorator);}}} catch (Exception ex) {for (RestTemplateSpanDecorator spanDecorator : spanDecorators) {try {spanDecorator.onError(httpRequest, ex, span);} catch (RuntimeException exDecorator) {log.error("Exception during decorating span", exDecorator);}}throw ex;} finally {span.finish();}return httpResponse;
}

上述实现中,在请求前,请求后以及报错时使用了RestTemplateSpanDecorator来装饰Span,所以RestTemplateSpanDecorator也是一个重要的扩展点,具体如何使用,在后续的文章中会逐步进行演示。

2. Injector和Extractor

InjectorExtractor分别用来处理SpanContext的注入和提取操作,以Jaeger为例,在创建JaegerTracer时,可以按照键值对的方式,向JaegerTracer注册InjectorExtractor,就像下面这样。

@Configuration
public class TracerConfig {@Autowiredprivate SpanReporter spanReporter;@Autowiredprivate Sampler sampler;@Beanpublic Tracer tracer(MyHttpHeadersInjector myHttpHeadersInjector,MyHttpHeadersExtractor myHttpHeadersExtractor) {return new JaegerTracer.Builder(TRACER_SERVICE_NAME).withTraceId128Bit().withSampler(sampler).withReporter(spanReporter).registerInjector(Format.Builtin.HTTP_HEADERS, myHttpHeadersInjector).registerExtractor(Format.Builtin.HTTP_HEADERS, myHttpHeadersExtractor).build();}}

键是Format,可以自己定义,也可以使用Opentracing为我们定义好的,例如Format.Builtin#HTTP_HEADERS,值就是InjectorExtractor的实现类,那么我们就可以自己提供InjectorExtractor的实现类来扩展SpanContext的注入和提取操作。

3. ScopeManager

大多数情况下,Opentracing提供的ThreadLocalScopeManager能满足我们的使用需求,但如果是异步链路追踪的场景,ThreadLocal就无法满足使用需求,此时需要使用InheritableThreadLocal,我们就可以基于InheritableThreadLocal来提供一个ScopeManager接口的实现类,并在创建Tracer时指定我们要使用的ScopeManager。还是以Jaeger为例,在创建JaegerTracer时,可以指定要使用的ScopeManager,如下所示。

@Configuration
public class TracerConfig {@Autowiredprivate SpanReporter spanReporter;@Autowiredprivate Sampler sampler;@Beanpublic Tracer tracer(ScopeManager scopeManager) {return new JaegerTracer.Builder(TRACER_SERVICE_NAME).withTraceId128Bit().withSampler(sampler).withReporter(spanReporter).withScopeManager(scopeManager).build();}}

具体如何使用,以及如何基于InheritableThreadLocal来实现适用于异步链路追踪的ScopeManager,这里就不再深入,这一块儿将在后续的文章中进行分析和演示。

4. 其它扩展点

扩展点还有很多,限于本文篇幅,这里就不再一一介绍,后面在实现分布式链路工具包的时候,用到了,自然会进行说明。

总结

一不小心,又扯了这么多,本文其实重点就是聚焦于Opentracing中的若干重要概念,这里用于一张图进行总结吧。

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

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

相关文章

JavaWEB 框架安全:Spring 漏洞序列.(CVE-2022-22965)

什么叫 Spring 框架. Spring 框架是一个用于构建企业级应用程序的开源框架。它提供了一种全面的编程和配置模型,可以简化应用程序的开发过程。Spring 框架的核心特性包括依赖注入(Dependency Injection)、面向切面编程(Aspect-Or…

AIGC绘画辅助网站

Midjourney风格样式 Midjourney Style Classifier | Andrei Kovalevs Midlibrary

124.反转链表(力扣)

题目描述 代码解决(思路1:双指针) class Solution { public:ListNode* reverseList(ListNode* head) {ListNode*temp;//保存cur下一个节点ListNode*curhead;ListNode*preNULL;while(cur){tempcur->next;// 保存一下 cur的下一个节点&#…

【图论】Floyd

算法-Floyd 前置知识 dp基础图论基础 思路 Floyd 是一种优秀的全源最短路算法。 它的执行过程类似于 dp,如下: 首先我们定义 d [ i ] [ j ] d[i][j] d[i][j] 为节点 i i i 到节点 j j j 的最短距离。 我们枚举中转节点 k k k,再枚举两个…

接口自动化测试的最佳实践和常见错误!

引言: 随着软件开发的不断演进,接口自动化测试在软件质量保障的过程中扮演着越来越重要的角色。良好的接口自动化测试可以提升测试效率、减少人力成本,但同时也存在着一些常见错误。本文将从零到一详细介绍接口自动化测试的最佳实践和常见错…

open-vm-tools使用虚机的拷贝/粘切

open-vm-tools 是一组用于 VMware 虚拟机中的开源工具,它们提供了一些与虚拟机操作和管理相关的功能。这些工具与 VMware 虚拟化平台集成,可以在虚拟机中提供更好的性能和功能。以下是一些 open-vm-tools 提供的功能: 1. 虚拟机增强功能: open-vm-tools 提供了与 VMware 虚…

node.js中的断言

assert.ok(value, [message]):如果value不为真,则抛出一个AssertionError,可选地包含message。 const assert require(assert); assert.ok(true); // 没有错误 assert.ok(false, 这里应该是true); // 抛出 AssertionError: 这里应该是tru…

突破传统 重新定义:3D医学影像PACS系统源码(包含RIS放射信息)实现三维重建与还原

突破传统,重新定义PACS/RIS服务,洞察用户需求,关注应用场景,新一代PACS/RIS系统,系统顶层设计采用集中分布式架构,满足医院影像全流程业务运行,同时各模块均可独立部署,满足医院未来影像信息化扩展新需求、…

Ecovadis认证是什么?

Ecovadis认证是一种企业社会责任(CSR)评估和评级的认证,旨在衡量企业在环境、劳工和人权、道德以及可持续采购四个方面的可持续发展表现。该认证已成为全球范围内许多公司和组织的评估标准之一,有助于提高企业的会声誉和可持续发展…

Linux专栏10:Linux权限详解(上)

博客主页:Duck Bro 博客主页系列专栏:Linux专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Linux权限详解(上) 编号:10 文章…

Leetcode274

题目 274. H 指数 思路 题目有点绕,最开始就想到了对数组进行排序,那就可以通过下标来得到有多少篇论文的引用大于等于当前论文的引用,如果大于了当前论文的引用量则将当前论文的引用量更新为h值。后面考虑到[3,3]这种情况,也就是…

String.intern()的作用

在Java中,String.intern() 是一个非常特殊的方法,它用于处理字符串常量池。字符串常量池(String Pool)是Java堆内存的一个特定区域,用来存储字符串字面量和显式调用 intern() 方法的字符串实例。这个池的目的是避免在J…

商务分析方法与工具(四):Python的趣味快捷-简单函数你真的会用吗?

Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊! 喜欢我的博客的话,记得…

SolidWorks进行热力学有限元分析一、模型建立

1.话不多说按照我的操作来 2.这一步鼠标移到中心点直接拉就行 3.这里选单位,继续按照操作来 4.选中这个边,直接拉,输入尺寸后确定,其他边同理 5.鼠标右键设置厚度 6.右键零件,然后编辑材料,给他赋予你需要的…

游戏辅助 -- 实战找人物对象基址

本节课在线学习视频: https://pan.quark.cn/s/3e83f4568031 一、打开CE工具,加载游戏进程 二、搜索人物血量144,选择首次扫描 三、进入游戏,让人物血量发生变化,搜索减少的数值 四、发现绿色的数值,一般绿…

Stable Diffusion:AI绘画的新纪元

摘要: Stable Diffusion(SD)作为AI绘画领域的新星,以其开源免费、强大的生成能力和高度的自定义性,正在引领一场艺术与技术的革命。本文旨在为读者提供Stable Diffusion的全面介绍,包括其原理、核心组件、安…

linux的信号量的使用

1.信号量 在多线程情况下,线程要进入关键代码就得获取信号量(钥匙){sem_init(&sem, 0, 0);},没有信号量的情况下就一直等待sem_wait(&sem),只到别人把钥匙(sem_post(&sem))给你。 …

分析错误ValueError: could not determine the shape of object type ‘Series‘

这个错误提示 ValueError: could not determine the shape of object type Series 通常发生在尝试将 pandas 的 Series 直接转换为 PyTorch 的 tensor 时,尤其是当 Series 的数据类型不明确或者包含非数值类型的数据时。为了修正这个问题,确保在转换之前…

npx 有什么作用跟意义?为什么要有 npx?什么场景使用?

npx 是 npm 从 v5.2.0 开始新增了 npx 命令,> 该版本会自动安装 npx,如果不能使用就手动安装一下: $ npm install -g npxnpx 的作用 npm 只能管理包的依赖,npx 则可以快捷的运用包中的命令行工具和其他可执行文件&#xff0c…

如何做好一个活动策划?

活动策划的关键要素是什么? 首先,要明确一个概念:做活动就是走钢丝,没有保险的高空走钢丝!因为,活动没有“彩排”,只有现场"直播”! 无论什么类型的活动,人数是50人还是2000人,也不论预算…