【Takin使用日记】记一次TransmittableThreadLocal引起的业务异常

对于常见的WEB容器,Takin通过增强org.apache.catalina.core.StandardHostValve#invoke方法,拦截并解析方法入参的Request对象中的header数据,判断压测标的信息并将压测标以及链路信息设置到上下文对象,并通过ThreadLocal保存该上下文对象,以此来保证当前线程处理的过程中都能获取到压测标以及链路信息。
在这里插入图片描述

但是不管是WEB容器还是业务代码经常会使用线程池运行代码,这时候ThreadLocal就有局限性了,如何做到跨线程池传递我们的上下文对象就显得异常重要了,好在Alibaba的https://github.com/alibaba/transmittable-thread-local解决了这个问题,具体transmittable-thread-local的详细内容大家可以通过git地址查看,这里我们主要以git上的demo看看transmittable-thread-local如何实现跨线程传递的,主要通过将线程池运行的Runnable对象包装成TtlRunnable对象并保存当前的上下文信息。这样就完成了对线程池运行任务的压测标以及链路数据信息的透传,至此似乎一切都很完美。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

直到某次出现了一个诡异的现象,在使用Takin的过程中,有一应用接入Takin之后,某个功能无法正常使用,但是无论是应用的日志还是Takin的日志都未显示任何异常信息,再追问了无法使用的功能是一个线程池执行任务,当时扩展了ThreadPoolExecutor的beforeExecute方法和afterExecute方法,用以记录任务执行的耗时,并且会打印任务的taskId等信息,通过截图的Debug信息便可以看到问题出现了,由于使用了transmittable-thread-local导致原始的Runnable被包装成了TtlRunnable对象,在这个过程中如果业务想要再获取Runnable对象强转获取一些任务信息,就会出现类无法转换的异常。

解决方案的话目前可以通过增强beforeExecute和afterExecute方法,对Runnable对象进行判断,如果是TtlRunnable对象,则通过TtlRunnable.getRunnable()方法返回原是的Runnable对象

在这里插入图片描述
在这里插入图片描述

Takin开源详情https://news.shulie.io/?p=3024
立即扫码,入群技术交流~
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值