我正在开发一个需要显示 CPU 使用率以及远程机器的其他系统信息的项目。人们建议使用 SIGAR 来实现这一点,但我不知道如何使用它。源代码对我来说不太有意义。基本上,我的问题是:如何在提供主机 IP 和 JMX 端口时将 SIGAR 提供的 MBean 注册到服务器,以及之后如何从其他计算机获取系统信息。如果我对 JMX 的工作方式有误,请纠正我。提前致谢。
3 回答
在我看来,您将不得不编写一些包装对象以将各种 SIGAR 输出公开为 JMX mbean 属性。您如何做到这一点在很大程度上取决于您使用什么来公开您的 JMX bean。我将为各种不同类型的 SIGAR 输出中的每一种编写一个包装对象:内存、磁盘、...
我编写了一个SimpleJMX 库,可能会有所帮助。我将使用它的格式提供一个示例对象,您可以使用它通过 JMX 公开信息。您可以将其调整为用于发布 JMX 的任何机制。我对 SIGAR 不够熟悉,无法知道我下面的 sigar 代码是否正确获取ProcMem
实例。
@JmxResource(description = "Show SIGAR Info", domainName = "foo")
public class SigarProcMem {
private ProcMem procMem;
{
// sorry, I'm not up on sigar so I'm not sure if this works
Sigar sigar = new Sigar();
procMem = sigar.getProcMem(sigar.getPid());
}
@JmxAttributeMethod(description = "Resident memory")
public long residentMemory() {
return procMem.getResident();
}
@JmxAttributeMethod(description = "Get the Total process virtual memory")
public long totalVirtualMemory() {
return procMem.getSize();
}
}
这些是您可以注册的 Sigar 内置 MBean 的类的名称:
- org.hyperic.sigar.jmx.SigarCpu
- org.hyperic.sigar.jmx.SigarCpuInfo
- org.hyperic.sigar.jmx.SigarCpuPerc
- org.hyperic.sigar.jmx.SigarLoadAverage
- org.hyperic.sigar.jmx.SigarMem
- org.hyperic.sigar.jmx.SigarProcess
- org.hyperic.sigar.jmx.SigarRegistry
- org.hyperic.sigar.jmx.SigarSwap
但是,远程部署这些将非常复杂,因为 Sigar 依赖于本地库,当加载 MBean 时,该库必须位于目标 JVM 的 lib-path 中。这意味着,您需要在要监控的每个目标主机上主动加载库和 MBean。
您可能能够破解一种通过远程调用使目标 JVM 加载它的方法,但这并不重要,并且需要您绕过 JVM 中的任何安全设置,因为默认情况下,这是您不应该做的能够做到。
您可以通过破解系统部分来轻松部署 Sigjar:
private String before;
private Sigar sigar;
/**
* Constructor - don't forget to call unload later!
*/
public SetlogSigar() throws Exception {
before = System.getProperty("java.library.path");
String path = "";
String add = getJarFolder();
if (before.contains(";"))
path = before + ";./;" + add;
else
path = before + ":./:" + add;
setSystemPath(path);
sigar = new Sigar();
}
/**
* This is needed to dynamically update the JAVA Path environment in order to load the needed native library
* Yes -rather an ugly hack...
*/
private String getJarFolder() {
// get name and path
String path = SetlogSigar.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = path;
try {
decodedPath = URLDecoder.decode(path, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
File f = new File(decodedPath);
String absolutePath = f.getParentFile().getParentFile().getParentFile().getParent()+"/lib";
return absolutePath;
}
/**
* Unloads the JNI bindings
*/
public void unload() {
this.sigar.close();
setSystemPath(before);
}
此 hack 将 sigjar.jar 所在的文件夹动态添加到环境变量中。只需将所有本机库放在那里,部署就会变得不那么复杂。