【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

调用链系列四:调用链上下文传递

  • 2020-02-12
  • 本文字数:3328 字

    阅读完需:约 11 分钟

调用链系列四:调用链上下文传递

在之前的调用链系列文章中,我们已经对调用链进行了详细介绍,相信大家已经对调用链技术有了基本的了解。


其实,在调用链的绘制过程中,调用链上下文的传递非常值得关注。各个节点在获取上层上下文后生成新的上下文并向后传递。在传递过程中,上下文一旦丢失或出现异常就会导致调用链数据缺失,甚至可能会发生断裂。


本文主要讲述 UAV 中调用链上下文传递过程中的部分实现细节。




前言


在调用链的实现中,主要存在以下几种调用链上下文的传递方式:


  • 请求处理前到请求处理后的上下文传递;

  • 各个客户端调用间的上下文传递;

  • 各个服务间调用时的上下文传递。


在这三种情况中,上下文传递过程中所传递的信息以及遇到的问题会有所不同。


  • 在请求处理前后的上下文传递过程中,需要传递的信息一般包括 traceID、 spanID、请求开始的时间以及部分请求参数等。相关代码可能会因为异步执行导致上下文面临异步线程传递的问题。

  • 在客户端调用间及服务间调用中,需要传递的上下文信息一般只包括 traceID 和 spanID。但客户端调用之间的上下文传递可能会遇到跨线程池传递的问题,服务间调用则存在跨应用传递的问题。


因此,我们把今天所讲的上下文传递划分为以下四种场景进行分析:


1、在同一线程内传递


2、跨线程池传递


3、异步线程传递


4、跨应用传递


为了更好地阐述这四种场景,我们假设存在以下业务调用过程:


1550129281876017593.png


假设某次请求首先进入服务 A,在服务 A 的业务代码中发起了一次 JDBC 请求,访问了一次数据源;然后又通过 httpClient(同步,异步)发起了一次 http 访问并返回相应结果。


数字表示所在点存在调用链上下文信息的获取。在大多数的相邻点之间都会涉及到调用链上下文的传递。


例如,从 2 点到 3 点就是请求前和请求后的上下文传递,从 3 点到 4 点就是两次客户端调用间的上下文传递,从 4 点到 5 点就是服务间的上下文传递。下面我们将在不同的场景下说明各点之间的上下文传递过程。

1.在同一线程内的上下文传递

这种场景比较常见,也是最简单的场景。


假设上述模拟流程中全部为同步操作,业务代码中不涉及任何的线程池(数据库连接池不影响)及异步操作,那么服务 A 中调用链的相关代码均会在同一个线程中执行。


说到这里,想必大家都会想到使用 ThreadLocal 便可以解决。使用 ThreadLocal 的确可以解决同线程中的参数共享传递问题。在 UAV 中,一般两次客户端调用之间的上下文传递都直接使用 ThreadLocal(其实并不是原生的 ThreadLocal,后文会有所介绍),传递过程如下:


1550129297901025915.jpg


但是很多时候,业务代码中经常会涉及到异步或者提交线程池的操作,此时单单使用 ThreadLocal 便无法满足相应的需求。下面我们就来讨论有关含有线程池操作和异步请求的上下文传递问题。



2.跨线程池的上下文传递

首次我们来看一下跨线程池上下文传递问题。


假设上述的业务场景中在进行 JDBC 操作时,当前线程仅负责将 JDBC 操作提交到线程池中,那么此时上下文信息从 1 点传递到 2 点就会遇到跨线程池的问题,此时使用 ThreadLocal 无法上下文信息的传递。


当然有的同学可能会说用 InheritableThreadLocal。但是提交线程和线程池线程本身并不存在父子关系,因此 InheritableThreadLocal 也是无法完成跨线程池的上下文传递的。


为了解决这个问题,我们使用了阿里开源的跨线程池的 ThreadLocal 组件:transmittable-thread-local(以下简称 TTL,具体的实现方式有兴趣的同学可以去了解下https://github.com/alibaba/transmittable-thread-local)


通过该组件可以增强 ThreadLocal 的功能实现跨线程池的传递。以下是 github 中 TTL 的使用示例:


TransmittableThreadLocal


parent.set(“value-set-in-parent”);


Runnable task =new Task(“1”);


// 额外的处理,生成修饰了的对象 ttlRunnable


Runnable ttlRunnable = TtlRunnable.get(task);


executorService.submit(ttlRunnable);


// Task 中可以读取,值是"value-set-in-parent"


String value = parent.get();


可以看到,想要 TTL 起作用,就需要将业务代码中的 runnable 更换为 TtlRunnable。为了实现对业务代码的零入侵,我们借助 javaagent 机制增加了一个针对 ThreadPoolExecutor 等一些 Eexecutor 的 ClassFileTransformer,将提交到线程池中的 Runnable 和 Callable 包装成相应的 TtlRunnable 和 TtlCallable,这样就实现了在不修改业务代码的情况下完成跨线程池的上下文传递。


另外,由于 TTL 具备 ThreadLocal 的所有特性,因此 UAV 的上下文传递过程中用到的 ThreadLocal 均是 TTL。

3.异步线程中上下文传递

看完上面的跨线程池操作,我们再来看一下异步线程的问题。


假设在上述模拟场景中,我们使用异步 HttpClient 发送了一个异步的 Http 请求。由于是异步操作,4 点的代码和 7 点的代码(这里 7 点的上下文是从 4 点中获取的属于请求前后的上下文获取场景)实际上会在不同的线程中执行,导致 7 点无法获取 4 点放入 ThreadLocal 中的上下文数据,进而导致调用链的数据丢失。


为了解决这个问题,在 UAV 中我们同时使用了字节码改写和动态代理技术。关键在于目标劫持函数的选择,需要能够获取到异步线程的回调对象。


下面以异步 HttpClient 为例介绍 UAV 中异步线程上下文的传递过程。


在异步 HttpClient 中,我们劫持的是 InternalHttpAsyncClient 类的 execute()方法,该方法声明如下:


1550129319021009666.png


一般情况下,异步的使用方式为传入一个 callback 接口对象,在 callback 中实现相应的异步逻辑;或者使用返回的 Future 接口对象的 get()方法实现一种异步转同步的操作。


为了能够在相应的地方获取到调用链的上下文,我们首先通过改写字节码的方式,在方法执行前生成调用链的上下文信息;然后对 FutureCallback 接口做动态代理,同时将生成的上下文信息传入到代理对象中,并替换原来的 callback 对象。


这样当异步请求返回调用 callback 接口时,实际上拿到的是我们的代理对象,此时也就完成了异步线程中上下文的传递过程,具体过程如下:


1550129333027072293.jpg


为了支持通过 get()方法的异步转同步操作,在这里我们也对返回的 Future 接口做了动态代理来完成上下文的传递。

4.跨应用上下文传递

说完应用内的上下文传递过程,我们来看一下跨应用的上下文传递问题。


跨应用的场景也是比较常见的。在这种场景下,上下文传递的思路一般是将上下文的信息按照一定的协议反序列化,然后放入到请求的传输报文中;在下游服务中劫持请求,获取其中的信息完成上下文的传递。在整个处理过程中,不对应用报文解析造成任何影响。


常见的传输协议中如 HTTP 协议,Dubbo 的 RPC 协议,RocketMQ 的 MQ 协议等。这些协议一般会含有类似于头信息的结构,用于表示本次请求的额外信息。


我们恰好可以利用这一点,将上下文信息放入其中传输给下游服务,完成上下文的传递。


下面我们仍然以异步 HttpClient 来介绍 UAV 跨应用上下文的传递过程。


之前我们说过,在异步 HttpClient 中,我们劫持的是 execute()方法。在这个方法中,我们可以拿到 HttpAsyncRequestProducer 接口对象,具体接口如下:


1550129417726034155.png


通过其中的 generateRequest()方法,我们就可以拿到本次请求将要发送的 request 对象,利用 request 的 setHeader()方法,将调用链的上下文信息放入 Header 中传入下游。


这里的上下文一般比较简单,基本上都是由 traceID 和 spanID 的字符串构成,传输成本也不高。


至于下游服务中如何解析该上下文,实际上之前的调用链系列中有谈到,就是借助 UAV 的中间件增强框架(MOF),在服务端劫持请求对应的 request 对象,然后直接从其头信息中获取即可。


1550129392978049116.jpg


其他的 RPC 或者 MQ 等协议,在 UAV 中均是采用这种方式完成,只是具体的 API 和劫持点有所不同。


例如,Dubbo 远程调用过程中使用是其中的 RpcContext,而 RocketMQ 则是放入到了 msg 的 UserProperty 中。感兴趣的同学可以到 UAVStack(https://github.com/uavorg/uavstack)中查看相关的源码。


总结


了解这些上下文的传递过程后,大家便可以基于调用链实现更为强大的功能。UAV 中,调用链和日志关联功能就是通过劫持日志输入部分的相关代码,获取调用链上下文,然后将 traceID 输出到业务日志中来实现的。


大家也可以自己在业务代码中尝试获取调用链的上下文,将业务数据与调用链数据打通,方便数据统计和问题排查。


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/221


2020-02-12 15:251278

评论

发布
暂无评论
发现更多内容

五大场景告诉你,如何把iPaaS运用到实处

RestCloud

数据同步 数据同步工具 ipaas

“创新启变 聚焦增长”极狐(GitLab)媒体沟通会,共话智能时代软件开发新生态

Geek_2d6073

语音识别技术:端到端的挑战与解决方案

来自四九城儿

面对纷繁复杂的低代码和无代码产品,开发者该如何选择?

这我可不懂

低代码 无代码

软件测试/测试开发丨深入了解性能测试:方法、工具和最佳实践

测试人

软件测试 性能测试 测试开发

敏捷思维和免费敏捷管理工具

顿顿顿

敏捷项目管理 敏捷开发管理工具 scrum工具 scrum敏捷工具 敏捷开发工具

9款好用的在线流程图软件推荐!

彭宏豪95

效率 流程图 在线工具 科技 流程图绘制

TiDB 7.4 发版:正式兼容 MySQL 8.0

编程猫

AI做体育赛事解说员,比赛观看平台开发搭建AI解说升级探究

软件开发-梦幻运营部

Generative AI 新世界 | 大模型参数高效微调和量化原理概述

亚马逊云科技 (Amazon Web Services)

人工智能 机器学习 生成式人工智能 Amazon SageMaker 大语言模型

稳定币揭幕:了解发展策略

区块链软件开发推广运营

数字藏品开发 dapp开发 区块链开发 链游开发 NFT开发

腾讯云发布新品数据编排平台(dop)-与大数据生态紧密结合,提供通用数据编排服务

腾讯云大数据

大数据

大规模语言LLaVA:多模态GPT-4智能助手,融合语言与视觉,满足用户复杂需求

汀丶人工智能

人工智能 计算机视觉 GPT 大语言模型

大模型背景下软件工程的机遇与挑战

CODING DevOps

语音识别技术的行业应用与发展趋势

来自四九城儿

低代码系列——可视化编辑器

互联网工科生

低代码 可视化编排

开放原子开源基金会开源安全委员会九月新增成员单位

开放原子开源基金会

低代码:时代的选择

树上有只程序猿

低代码 低代码开发平台

阿里内推强推的并发编程学习笔记,原理+实战+面试题,面面俱到!

小小怪下士

Java 程序员 并发编程

Audio Hijack for Mac(音频录制软件) 4.2.5完整版

mac

苹果mac Windows软件 Audio Hijack 音频录制软件

语音识别技术的挑战与机遇再探讨

来自四九城儿

消除隐患 防患未然|AIRIOT智慧消防管理解决方案

AIRIOT

数字化转型与架构-架构设计篇|系统组件有哪些?

数字随行

数字化转型

Hyperworks对比其他仿真软件有哪些特色_Hyperworks介绍

智造软件

CAE软件 altair hyperworks

从手动操作到自动化管理,如何实现企业身份业务全面自动化?

Authing

事件驱动 企业管理 Authing 身份自动化

OpenHarmonyMeetup2023深圳站圆满举办

科技热闻

2023-10-18:用go语言,给定一个数组arr,长度为n,表示有0~n-1号设备, arr[i]表示i号设备的型号,型号的种类从0~k-1,一共k种型号, 给定一个k*k的矩阵map,来表示型号

福大大架构师每日一题

福大大架构师每日一题

Acrobat Pro DC 2023(PDF编辑软件)mac/win

iMac小白

Acrobat DC 2023 PDF编辑软件 Acrobat DC 2023破解版 Acrobat DC 2023下载

等不及了,2023云栖大会精彩剧透提前看!

阿里云视频云

云计算 云栖大会

软件开发“自我毁灭”的七宗罪

高端章鱼哥

计划 软件开发

Disruptor在流程编排中的应用与探索

ZA技术社区

金融科技 众安保险 ZA技术社区 keji

调用链系列四:调用链上下文传递_区块链_朱文强_InfoQ精选文章