Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2036
  • 博文数量: 2
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 20
  • 用 户 组: 普通用户
  • 注册时间: 2021-07-23 17:32
文章分类

全部博文(2)

文章存档

2021年(2)

我的朋友
最近访客

分类: 系统运维

2021-08-13 11:19:29

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




但是不管是 WEB 容器还是业务代码经常会使用线程池运行代码,这时候 ThreadLocal 就有局限性了,如何做到跨线程池传递我们的上下文对象就显得异常重要了,好在 Alibaba 的解决了这个问题,具体 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 开源详情


阅读(741) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~