alibaba / transmittable-thread-local

📌 a missing Java std lib(simple & 0-dependency) for framework/middleware, provide an enhanced InheritableThreadLocal that transmits values between threads even using thread pooling components.
https://github.com/alibaba/transmittable-thread-local
Apache License 2.0
7.59k stars 1.69k forks source link

与其他探针放在一起使用的时候,如果ttlagent顺序在其他探针之后,探针失效无法跨线程 #525

Open will-zdu opened 1 year ago

will-zdu commented 1 year ago
private static ThreadLocal<String> threadLocal = new TransmittableThreadLocal<>();

ExecutorService executorService = Executors.newFixedThreadPool(2);

@GetMapping("local")
public String ttLocal(){
    String randomStr = UUID.randomUUID().toString();
    threadLocal.set(randomStr);
    Runnable runnable= new Runnable() {
        @Override
        public void run() {
            if (!randomStr.equals(threadLocal.get())){
                System.out.println("randomStr not equals localStr.");
            }
        }
    };
    executorService.execute(runnable);
    return "ok";
}

使用TTL Agent加其他AgentTTL Agent顺序在最后,runnable无法改成TtlRunnable

问题原因:其他探针启动的时候使用了ThreadPoolExecutor,导致TTL Agent没有机会transform ThreadPoolExecutor

will-zdu commented 1 year ago

解决方案:在添加transformer之后,将需要的嵌码类retransform一下

oldratlee commented 1 year ago

使用TTL Agent加其他AgentTTL Agent顺序在最后,runnable无法改成TtlRunnable

@will-zdu 在文档 FAQ 中已说明: https://github.com/alibaba/transmittable-thread-local/tree/2.x#-faq

Q1. TTL Agent与其它Agent(如SkywalkingPromethues)配合使用时不生效?

配置TTL Agent在最前的位置,可以避免与其它其它Agent配合使用时,TTL Agent可能的不生效问题。配置示例:

java -javaagent:path/to/transmittable-thread-local-2.x.y.jar \
     -javaagent:path/to/skywalking-agent.jar \
     -jar your-app.jar

原因是:

  • Skywalking这样的Agent的入口逻辑(premain)包含了线程池的启动。
  • 如果配置在这样的Agent配置在前面,到了TTL Agent(的premain)时,TTL需要加强的线程池类已经加载(load)了。
  • TTL AgentTtlTransformer是在类加载时触发类的增强;如果类已经加载了会跳过TTL Agent的增强逻辑。

更多讨论参见 Issue:TTL agent与其他Agent的兼容性问题 #226


解决方案:在添加transformer之后,将需要的嵌码类retransform一下

嗯嗯,欢迎讨论与实现 @will-zdu

oldratlee commented 1 year ago

@will-zdu PR #526 的实现,你有测试验证过吗(比如在你的应用中可以解决问题)?

这样简单处理可能是不行的,具体可以看看已有的讨论 Issue #226

will-zdu commented 1 year ago

已经测试验证过了,问题已经解决,当然我只测试了ThreadPoolExecutor类。

我看 #226 里面的讨论是ttl agent会尝试修改类文件结构?如果是这样的话,那确实是存在问题,请问是在那个地方修改了那个类的类文件结构

如果是这样的话,我认为ttl agent这样的修改不太好,修改类的结构在我看来是个不提倡的操作

oldratlee commented 1 year ago

retransformTTL Agent的实现变复杂了(如类的加载过程), 会引入还不知道的问题要解决(考虑Java Agent的复杂性), 进而影响TTL Agent整体的稳定性可靠性。

如果只是解决Agent配置的顺序问题,推荐配置TTL Agent到前面吧,简单可靠。 😄 @will-zdu


已经测试验证过了,问题已经解决,当然我只测试了ThreadPoolExecutor类。

当然,你的实现可以自己打个包,在你自己应用中用起来。 💕 @will-zdu 欢迎反馈实现在应用使用中的情况~


我认为ttl agent这样的修改不太好,修改类的结构在我看来是个不提倡的操作

欢迎给出不同的实现与验证 💕

will-zdu commented 1 year ago

如果没有修改类文件结构,使用retransform transform该类没有任何的问题,以我们探针这么多年的使用经验来说,除了需要短暂的进入safepoint,挂起jvm,没有发现有任何问题,当然进入safepoint是必须的,我觉得可以暂时将ForkJoinPool移除retransform的类列表

will-zdu commented 1 year ago

我把代码修改了一下,将ForkJoinPool移除retransform的类列表,这样应该是可以工作了,但是如果别的探针触发了ForkJoinPool的retransform,问题依然是存在的