效果
先来看一下实现后的效果。默认是cpu使用率倒序排,并且支持磁盘,内存使用率倒序展示。后期监控平台很方便。
前言
最近临近双11,搜索平台业务共用的机器报出很多cpu使用率超过90%的异常,由于机器很多,报出异常后还需要手动上itsm平台上的zabbix查看,itsm根据ip查询机器会很不友好的弹出很多页面,而且需要每个ip查一下,很容易造成浏览器页面堆积一堆,然后查出来的告警机器ip还要手动记录,感觉超级麻烦。
利用sigar实现服务器监控
所以想通过java实现服务器监控,然后在搜索平台页面上展示出来,目前常用的就是磁盘,cpu,内存使用率。
sigar简介
sigar全名是System Information Gatherer And Reporter,Sigar是Hyperic-hq产品的基础包,是Hyperic HQ主要的数据收集组件。它用来从许多平台收集系统和处理信息。
这些平台包括:Linux, Windows, Solaris, AIX, HP-UX, FreeBSD and Mac OSX.
Sigar有C,C#,Java和Perl API,java版的API为sigar.jar sigar.jar的底层是用C语言编写的,它通过本地方法来调用操作系统API来获取系统相关数据。
Windows操作系统下Sigar.jar 依赖sigar-amd64-winnt.dll或sigar-x86-winnt.dll,
linux 操作系统下则依赖libsigar-amd64-linux.so或libsigar-x86-linux.so
通过他可以获得系统的如下介个方面的信息:
1.操作系统的信息,包括:dataModel、cpuEndian、name、version、arch、machine、description、patchLevel、vendor、vendorVersion、vendorName、vendorCodeName
2.CPU信息,包括:基本信息(vendor、model、mhz、cacheSize)和统计信息(user、sys、idle、nice、wait)
3.内存信息,物理内存和交换内存的总数、使用数、剩余数;RAM的大小
4.进程信息,包括每个进程的内存、CPU占用数、状态、参数、句柄等。
5.文件系统信息,包括名称、容量、剩余数、使用数、分区类型等
6.网络接口信息,包括基本信息和统计信息。
7.网络路由和链接表信息。
sigar下载
Hyperic-hq官方网站:http://www.hyperic.com
Sigar.jar下载地址:http://sigar.hyperic.com
备用下载地址:点击下载
sigar为不同平台提供的不同库文件
window下需要将lib中sigar-amd64-winnt.dll文件拷贝到java SDK目录的bin内。
linux下需要将lib中libsigar-amd64-linux.so文件拷贝到/usr/lib64/目录的内
查看源码后,可以自定义库文件的路径的
比如搜索平台将文件放到了/opt/files/search/public/sigar目录下
org.hyperic.sigar.path=/opt/files/search/public/sigar
File | Language | Description | Required |
---|---|---|---|
sigar.jar | Java | Java API | Yes (for Java only) |
log4j.jar | Java | Java logging API | No |
libsigar-x86-linux.so | C | Linux AMD/Intel 32-bit | * |
libsigar-amd64-linux.so | C | Linux AMD/Intel 64-bit | * |
libsigar-ppc-linux.so | C | Linux PowerPC 32-bit | * |
libsigar-ppc64-linux.so | C | Linux PowerPC 64-bit | * |
libsigar-ia64-linux.so | C | Linux Itanium 64-bit | * |
libsigar-s390x-linux.so | C | Linux zSeries 64-bit | * |
sigar-x86-winnt.dll | C | Windows AMD/Intel 32-bit | * |
sigar-amd64-winnt.dll | C | Windows AMD/Intel 64-bit | * |
libsigar-ppc-aix-5.so | C | AIX PowerPC 32-bit | * |
libsigar-ppc64-aix-5.so | C | AIX PowerPC 64-bit | * |
libsigar-pa-hpux-11.sl | C | HP-UX PA-RISC 32-bit | * |
libsigar-ia64-hpux-11.sl | C | HP-UX Itanium 64-bt | * |
libsigar-sparc-solaris.so | C | Solaris Sparc 32-bit | * |
libsigar-sparc64-solaris.so | C | Solaris Sparc 64-bit | * |
libsigar-x86-solaris.so | C | Solaris AMD/Intel 32-bit | * |
libsigar-amd64-solaris.so | C | Solaris AMD/Intel 64-bit | * |
libsigar-universal-macosx.dylib | C | Mac OS X PowerPC/Intel 32-bit | * |
libsigar-universal64-macosx.dylib | C | Mac OS X PowerPC/Intel 64-bit | * |
libsigar-x86-freebsd-5.so | C | FreeBSD 5.x AMD/Intel 32-bit | * |
libsigar-x86-freebsd-6.so | C | FreeBSD 6.x AMD/Intel 64-bit | * |
libsigar-amd64-freebsd-6.so | C | FreeBSD 6.x AMD/Intel 64-bit | * |
Java代码使用示例
/**
* 静态工具类获取cpu总使用率
* @throws SigarException
*/
public static String cpu() throws SigarException {
if(System.getProperty("org.hyperic.sigar.path")==null){
System.setProperty("org.hyperic.sigar.path","/opt/files/search/public/sigar");
}
Sigar sigar = new Sigar();
//CPU的总量(单位:HZ)及CPU的相关信息
CpuInfo infos[] = sigar.getCpuInfoList();
CpuPerc cpuList[] = null;
cpuList = sigar.getCpuPercList();
double combined = 0d;
for (int i = 0; i < infos.length; i++) {// 不管是单块CPU还是多CPU都适用
combined += cpuList[i].getCombined();
}
return CpuPerc.format(combined / cpuList.length);
}
/**
* 静态工具类:获取内存总使用率
* @throws SigarException
*/
public static String memory() throws SigarException {
Sigar sigar = new Sigar();
// 物理内存信息
Mem mem = sigar.getMem();
return CpuPerc.format(Double.valueOf(mem.getUsed()/ 1024L+"")/ Double.valueOf(mem.getTotal()/ 1024L+""));
}
/**
* 静态工具类:获取磁盘总使用率
* @throws Exception
*/
public static String file() throws Exception {
Sigar sigar = new Sigar();
//通过sigar.getFileSystemList()来获得FileSystem列表对象,然后对其进行编历
FileSystem fslist[] = sigar.getFileSystemList();
double combined = 0d;
for (int i = 0; i < fslist.length; i++) {
FileSystem fs = fslist[i];
FileSystemUsage usage = null;
usage = sigar.getFileSystemUsage(fs.getDirName());
switch (fs.getType()) {
case 0: // TYPE_UNKNOWN :未知
break;
case 1: // TYPE_NONE
break;
case 2: // TYPE_LOCAL_DISK : 本地硬盘
double usePercent = usage.getUsePercent();
// 文件系统资源的利用率
combined+=usePercent;
break;
case 3:// TYPE_NETWORK :网络
break;
case 4:// TYPE_RAM_DISK :闪存
break;
case 5:// TYPE_CDROM :光驱
break;
case 6:// TYPE_SWAP :页面交换
break;
}
}
return CpuPerc.format(combined / fslist.length);
}
引擎系统增加http接口
/**
* @Description: 获取服务器信息
* @param @param response
* @param @param model 模块(disk,cpu,memory)
* @return void 返回类型 (string,jsonstring)
* @throws
*/
@RequestMapping("/admin/getServerInfo.json")
public void getServerInfo(HttpServletRequest request,HttpServletResponse response) {
String module = request.getParameter("module");
try {
if("disk".equals(module)){
response.getWriter().write(SigarUtil.file());
}
else if("cpu".equals(module)){
response.getWriter().write(SigarUtil.cpu());
}
else if("memory".equals(module)){
response.getWriter().write(SigarUtil.memory());
}
else{
JSONObject jsonObject = new JSONObject();
jsonObject.put("disk",SigarUtil.file());
jsonObject.put("cpu",SigarUtil.cpu());
jsonObject.put("memory",SigarUtil.memory());
response.getWriter().write(jsonObject.toJSONString());
}
} catch (Exception e) {
logger.error("", e);
try {
response.getWriter().write(ERROR);
} catch (IOException e1) {
logger.error("", e1);
}
}
}
搜索平台获取服务器信息
/**
* 多线程轮训 根据ip获取并封装服务器使用率(磁盘,cpu,内存)
* @param engineManagementBean
*/
public List<EngineManagementBean> setServerInfoByIp(List<EngineManagementBean> engineManagementBean){
List<Future<EngineManagementBean>> engineManagementBeans = new ArrayList<>();
List<EngineManagementBean> lists = new ArrayList<>();
CompletionService<EngineManagementBean> completionService = newServerService();
for(final EngineManagementBean engineManagementBean1:engineManagementBean){
Callable<EngineManagementBean> task = new Callable<EngineManagementBean>() {
@Override
public EngineManagementBean call() {
String url = "Http://"+engineManagementBean1.getIp()+":8080/epbs/admin/getServerInfo.json?module=";
try {
String obj = HttpUtils.webget(url, 1000);
JSONObject jsonObject = JSON.parseObject(obj);
if(jsonObject!=null) {
engineManagementBean1.setDiskRate(jsonObject.get("disk").toString());
engineManagementBean1.setCpuRate(jsonObject.get("cpu").toString());
engineManagementBean1.setMemoryRate(jsonObject.get("memory").toString());
}
} catch (IOException e) {
log.error(url+" is excpetion {}",e);
}
return engineManagementBean1;
}
};
engineManagementBeans.add(completionService.submit(task));
}
while (!engineManagementBeans.isEmpty()) {
try {
Future<EngineManagementBean> future = completionService.take();
engineManagementBeans.remove(future);
EngineManagementBean rsp = null;
rsp = future.get();
lists.add(rsp);
} catch (InterruptedException e) {
log.error("Interrupted!{}", e);
Thread.currentThread().interrupt();
} catch (Exception e) {
log.error("Impossible Exception{}", e);
}
}
return lists;
}
/**
* 根据module,sort排序
* @param environmentList
* @param module dist,cpu,memory
* @param sort desc asc
*/
public void sortByServerInfo(List<EngineManagementBean> environmentList,final String module,final String sort){
Collections.sort(environmentList, new Comparator<EngineManagementBean>(){
/*
* 返回负数表示:p1 小于p2,
* 返回0 表示:p1和p2相等,
* 返回正数表示:p1大于p2
*/
@Override
public int compare(EngineManagementBean p1, EngineManagementBean p2) {
String s1 = "";
String s2 = "";
if("disk".equals(module)){
s1 = p1.getDiskRate();
s2 = p2.getDiskRate();
}else if("memory".equals(module)){
s1 = p1.getMemoryRate();
s2 = p2.getMemoryRate();
}else{
s1 = p1.getCpuRate();
s2 = p2.getCpuRate();
}
if("desc".equals(sort)){
if(Double.valueOf(s1.split("%")[0]) > Double.valueOf(s2.split("%")[0])){
return -1;
}
if(Double.valueOf(s1.split("%")[0])-Double.valueOf(s2.split("%")[0])==0.0){
return 0;
}
return 1;
}
else{
if(Double.valueOf(s1.split("%")[0]) > Double.valueOf(s2.split("%")[0])){
return -1;
}
if(Double.valueOf(s1.split("%")[0])-Double.valueOf(s2.split("%")[0])==0.0){
return 0;
}
return 1;
}
}
});
}