关于性能测试:Takin使用日记记一次TransmittableThreadLocal引起的业务异常

12次阅读

共计 1000 个字符,预计需要花费 3 分钟才能阅读完成。

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

然而不论是 WEB 容器还是业务代码常常会应用线程池运行代码,这时候 ThreadLocal 就有局限性了,如何做到跨线程池传递咱们的上下文对象就显得异样重要了,好在 Alibaba 的 https://github.com/alibaba/tr… 解决了这个问题,具体 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