在Plumbr,我们花了最后一个月的时间来为将来的重大改进奠定基础。 此类构件之一是为JVM添加唯一标识符,以便将来自同一JVM的所有会话链接在一起。
虽然一开始看起来似乎很琐碎的任务,但是当查看JVM捆绑的jps命令的输出时,围绕该问题的复杂性开始令人头疼,该命令列出了我的机器中所有当前正在运行的Java进程:
My Precious:tmp my$ jps
1277 start.jar
1318 Jps
1166
上面列出了jps命令的输出,列出了我的机器上当前正在运行的所有Java进程。 如果您不熟悉该工具,则它会在左侧列出所有进程的进程ID,并在右栏中列出进程名称。 显然,唯一一个以有意义的名称列出自己的人就是jps本身。 另外两个不太礼貌。 隐藏在start.jar首字母缩写后面的是Jetty实例,而完全匿名的实际上是Eclipse。 我的意思是,真的– Java世界上最大的IDE甚至不愿意在标准Java工具中用名称列出自己吗?
因此,一窥内置工具的最新技术,就可以回到我们手头的要求上。 我们当前的解决方案是通过进程ID +计算机名称组合来标识JVM。 这有一个明显的缺点–每当进程死掉时,它的轮回就不会从内核获得相同的ID。 因此,每当JVM Plumbr监视的监视重新启动或终止时,我们都会失去跟踪,无法将后续调用绑定在一起。 对于监视工具来说,这显然不是合理的行为,因此我们继续寻找更好的解决方案。
接下来的明显步骤是三个月前,当时我们允许用户通过-Dplumbr.application.name = my-precious-jvm启动参数指定计算机的名称。 看起来似乎很明智,但在这三个月中,只有2%的用户实际上不愿意指定此参数。 因此,现在该回到绘图板上,看看在尝试将唯一且易于理解的标识符自动绑定到JVM实例时,我们有哪些选择。
我们的第一种方法是使用main()方法获取类的名称,并将其用作标识符。 当我们在包含四个不同Jetty实例的开发箱中启动构建时,立即出现的弊端很快就会显现出来–您立即拥有四个不同的JVM,它们都在相同的但不太唯一的标识符下进行绑定。
下一个尝试是解析应用程序的内容并从部署描述符中识别应用程序–毕竟, Plumbr监视的大多数应用程序都打包为WAR / EAR捆绑软件,因此这将是有意义的,并使用捆绑软件中存在的信息。 实际上,绝大多数工程师的确在web.xml或application.xml的<display-name>参数中给出了有意义的名称。
这解决了部分问题–当所有四个Jetty实例都运行具有不同<display-name>的应用程序时,它们将显示为唯一。 确实如此,直到我们的登台环境表明情况并非总是如此。 我们在同一台计算机上有几个不同的Plumbr Server实例,它们使用不同的应用程序服务器,但是使用相同的<display-name>参数部署相同的WAR文件。 您可能会猜到,这再次扼杀了此类ID的唯一性。
另一个引起问题的事实是,有一些应用程序服务器正在运行多个Web应用程序-将多个WAR文件部署到容器中后会发生什么?
因此,我们不得不进一步挖掘。 为了区分在同一台机器上运行同一应用程序的多个JVM,我们添加了启动文件夹以保证标识符的唯一性。 但是多重战争的问题仍然存在。 为此,我们回到了最初的假设,即使用主类名称作为标识符。
还有一些技术上的细微差别,例如区分用于ID的实际哈希和同一哈希的用户友好版本,现在,我们提供了一种解决方案,它将在您监视的JVM列表中显示类似的内容:
机 | 虚拟机 | 由于 |
---|---|---|
青蒿素分期 | 自助服务(WAR) | 2014年7月7日11:45 |
青蒿素分期 | 网上商店(WAR) | 2014年8月7日18:30 |
芳纶 | com.ringbearer.BatchProcessor | 01.01.2001 00:00 |
因此,实际上,我们能够提出一个不错的解决方案,并在其他所有方法均失败的情况下使用-Dplumbr.application.name参数进行手动命名。 仍然存在一个问题–为什么JVM工具和API完全缺少系统管理员通常需要的东西?
翻译自: https://www.javacodegeeks.com/2014/07/identifying-jvm-trickier-than-expected.html