让 Java Agent 在 Dragonwell 上更好用
本文是《容器中的Java》系列文章之 3/n ,欢迎关注后续连载 :) 。
背景
Java Agent 技术能够动态修改 Java 应用程序行为,而不用重新修改代码。
正是因为这些特点,很多中间件团队、云厂商团队、开源产品,开始使用 Java Agent 技术来提供一些基础能力,比如 Apache Skywalking、OpenTelemetry 都提供了 Java Agent。
在早前,中间件团队通过SDK提供能力(比如可观测、微服务治理能力等);但中间件团队每次新增特性、修复缺陷,都需要各个业务方更新SDK版本、重新发布。
随着公司架构越来越复杂,随着云厂商开始提供中间件能力,这种逐个推动SDK使用方更新的方式越来越麻烦。
而用了 Java Agent 之后,业务同学只需要写业务代码;中间件能力通过设置环境变量来动态注入Java Agent来实现。Java Agent的更新,也只需要重启应用即可。
问题
我们以一个微服务demo为例。先在一个Kubernetes集群中部署demo,然后通过JAVA_TOOL_OPTIONS
使用用Java Agent:
1 | $ echo $JAVA_TOOL_OPTIONS |
我们登陆容器时,就能看到注入的 Java Agent:
但这样的结果是容器中所有的JVM,都会挂载 Java Agent。
比如就执行一个java -version
,也要加载 Java Agent:
还有jstack
也会加载 Java Agent :
- java/jps/jstack/jcmd等JDK自带的问题排查工具,都会去从环境变量加载Java Agent。
- 因为 Java Agent 是在JVM初期加载的,所以Java Agent会先耗费6-7s来加载agent逻辑。
- 但作为JDK工具,其实没有任何业务逻辑,不需要微服务治理能力。可以不用加载Java Agent的。
我们设想下这个场景:线上应用出现问题了,运维同学要抓现场,上去就想jstack拉一下stacktrace信息。
结果先要加载java agent,不但浪费了CPU和内存,更容易错过问题排查的现场。
但,一边要通过环境变量无侵入注入Java Agent,一边又要不在某些进程内注入。看起来无解了?
修复
首先,注入 Java Agent 与否,是JVM确定的。我们只需要修改 JVM 的判断逻辑即可。
在这一点上,Dragonwell团队有着丰富的经验。
其次,我们看下JVM的行为,现有的开源行为如下:
- JDK相关命令,都会从
JAVA_TOOL_OPTIONS
加载 Java Agent - OpenJDK9之后,引入了
JDK_JAVA_OPTIONS
,这个环境变量只会被java命令使用。jps/jstack等命令不会加载。 - 有些JDK厂商,会有自己的扩展环境变量, 比如,IBM会读取IBM_JAVA_OPTIONS,开源后的OpenJ9开始使用OPENJ9_JAVA_OPTIONS,Oracle/OpenJDK使用_JAVA_OPTIONS。
本来JDK_JAVA_OPTIONS
能够很好的满足需求,但作为“你发任你发,我用Java8”的业务开发同学,稳定为先,所以 Java 8 是一定要支持的。
经过和Dragonwell的讨(si)论(bi),确定了如下修改:
DRAGONWELL_JAVA_OPTIONS
,和IBM_JAVA_OPTIONS类似,设置某些只用于Dragonwell的Java参数。DRAGONWELL_JAVA_TOOL_OPTIONS_JDK_ONLY
,和JDK_JAVA_OPTIONS
类似。
如果DRAGONWELL_JAVA_TOOL_OPTIONS_JDK_ONLY
=true,则JAVA_TOOL_OPTIONS
只会被java命令加载。jps/jstack不会加载JDK_JAVA_OPTIONS
环境变量、不会加载Java Agent。
经过上面的改造,就可以做到只对业务Java进程加载 Java Agent 。同时不影响jps/jstack等JDK自带的运维命令。
当然,Dragonwell作为开源项目,讨论的整体流程都是在GitHub Issue上完成的,欢迎围观、吃瓜、吐槽:
https://github.com/alibaba/dragonwell8/issues/330#issuecomment-1138083844
最终效果
让我们使用最新的Dragonwell版本,跑一下业务应用,模拟一下运维场景:
可以看到,有JAVA_TOOL_OPTIONS
能够保证业务进程加载 Java Agent,同时也保证了 java -version
等JDK运维工具不会加载Java Agent了。
总结
在云原生领域,Java Agent作为一种无侵入、低开销的运行时增强能力,业务同学不同修改一行代码即可接入可观测、微服务治理等中间件能力。让业务专注于业务价值。
让 Java Agent 在 Dragonwell 上更好用
https://robberphex.com/java-agent-is-getting-better-at-dragonwell/