博客
关于我
skywalking 沉了一年的线程池插件 bug 被我解决了
阅读量:796 次
发布时间:2023-03-22

本文共 1468 字,大约阅读时间需要 4 分钟。

排查线程池插件增强失败的问题

在使用 Apache SkyWalking 的线程池插件时,可能会遇到 traceId 为空的问题。以下是详细的排查过程和解决方案。


问题背景

最近公司在进行全链路追踪,选择 Apache SkyWalking 作为核心实现工具。对于异步链路的 trace 覆盖,已经有了线程池插件(apm-jdk-threadpool-plugin.jar)。在应用中使用该插件时,发现线程池提交任务时 traceId 为空。经过初步排查,发现问题与类加载阶段的插件激活逻辑有关。


排查过程

  • 插件配置问题

    • 将插件 jar 包移动到 plugins 目录下,但应用启动后插件未生效。
    • 测试简化配置,仅保留 tomcat-7.x-8.x-pluginapm-jdk-threadpool-plugin,发现线程池插件生效。
  • 类加载器实例化问题

    • 发现 AgentClassLoader 实例化了两次,导致扫描 jar 包的日志多次输出。
    • 调试 AgentClassLoader 的构造器,发现第一次在 premain 方法启动时实例化,第二次在 main 方法启动时加载插件时再次实例化。
  • 日志扫描与依赖问题

    • InterceptorInstanceLoader 中发现,扫描 jar 包的逻辑存在缓存问题,可能导致多次扫描。
    • 发现 ThreadPoolExecutor 类在日志组件 FileWriter 中被多次依赖,导致增强失败。
  • 类加载顺序分析

    • 启动时开启 TraceClassLoading,观察到 ThreadPoolExecutor 类在 transform 阶段被依赖。
    • 发现 ThreadPoolExecutorFileWriter 中的初始化触发了 transform,而 transform 阶段依赖已加载的 ThreadPoolExecutor 类,导致循环依赖问题。
  • 解决方案

    • 修改 AgentClassLoader 为单例模式,避免重复实例化和多次扫描 jar 包。
    • FileWriter 中注释掉线程池的初始化代码,改为其他实现方式,避免对 ThreadPoolExecutor 的依赖。

  • 问题分析

  • 线程池插件为什么会失败?

    • 插件的字节码增强在类加载阶段进行,依赖类的加载顺序。
    • 如果已加载的类依赖需要增强的类,可能在 transform 阶段失败。
  • 重复实例化的影响

    • AgentClassLoader 实例化多次,导致日志多次输出,可能引发多次扫描 jar 包。
    • 重复扫描可能导致对 ThreadPoolExecutor 类的多次依赖,触发 transform 逻辑。
  • JVM 类加载机制的限制

    • JVM 对已加载类的 transform 有限制,可能避免循环依赖导致的问题。
    • 重复扫描 jar 包可能触发多次对 ThreadPoolExecutor 的依赖,导致增强失败。

  • 解决方案

  • 确保插件单例

    • 修改 AgentClassLoader 为单例模式,避免重复实例化和多次扫描 jar 包。
  • 优化日志组件

    • FileWriter 中注释掉线程池的初始化代码,改为其他实现方式,避免对 ThreadPoolExecutor 的依赖。
  • 简化插件测试

    • 单独测试插件,确保每个插件的增强逻辑独立,不互相依赖。

  • 代码示例(PR 链接)


    总结

    线程池插件的增强失败问题主要源于类加载顺序和重复实例化。通过确保插件单例和优化日志组件,可以有效解决问题。

    转载地址:http://isqfk.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现slow sort慢排序算法(附完整源码)
    查看>>
    Objective-C实现tanh函数功能(附完整源码)
    查看>>
    Objective-C实现z-algorithm算法(附完整源码)
    查看>>
    Objective-C实现zellers congruence泽勒一致算法(附完整源码)
    查看>>
    Objective-C实现Zero One Knapsack零一背包计算算法(附完整源码)
    查看>>
    Objective-C实现一个Pangram字符串至少包含一次所有字母算法(附完整源码)
    查看>>
    Objective-C实现一个通用的堆算法(附完整源码)
    查看>>
    Objective-C实现一分钟倒计时(附完整源码)
    查看>>
    Objective-C实现三次样条曲线(附完整源码)
    查看>>
    Objective-C实现上传文件到FTP服务器(附完整源码)
    查看>>
    Objective-C实现两数之和问题(附完整源码)
    查看>>
    Objective-C实现串口通讯(附完整源码)
    查看>>
    Objective-C实现串逐位和(附完整源码)
    查看>>
    Objective-C实现主存储器空间的分配和回收(附完整源码)
    查看>>
    Objective-C实现乘方运算---m的n次方(附完整源码)
    查看>>
    Objective-C实现二叉树遍历算法(附完整源码)
    查看>>
    Objective-C实现二进制和算法(附完整源码)
    查看>>
    Objective-C实现二进制补码算法(附完整源码)
    查看>>
    Objective-C实现互斥锁同步执行两个线程函数(附完整源码)
    查看>>
    Objective-C实现交易密码算法(附完整源码)
    查看>>