来源:http://www.cnblogs.com/haifg/p/3217699.html
最近项目需要监控服务器cpu的利用率,并做成动态图。在网上查找了一些资料,最终选择了HighChartS来做动态图。
HIghChartS官网:http://www.highcharts.com/
HighCharts Demo:http://www.highcharts.com/demo/
项目中参考的Demo:http://www.highcharts.com/demo/dynamic-update
完成这个cpu利用率的动态图,做了一个小的Demo,分为三层:界面层(jsp),控制层(servlet),模型层(javabean)。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script src="js/jquery.min.js"></script><!-- 1.8.2 -->
<script type="text/javascript">
$(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
//声明报表对象
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
defaultSeriesType: 'spline',
marginRight: 10
},
title: {
text: 'CPU使用率动态曲线图'
},
xAxis: {
title: {
text: '时间'
},
//linear" or "datetime"
type: 'datetime',
//坐标间隔
tickPixelInterval: 150
},
yAxis: {
title: {
text: '使用率'
},
//指定y=3直线的样式
plotLines: [
{
value: 0,
1,
color: '#808080'
}
]
},
//鼠标放在某个点上时的提示信息
//dateFormat,numberFormat是highCharts的工具类
tooltip: {
formatter: function() {
return '<b>' + this.series.name + '</b><br/>' +
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' +
Highcharts.numberFormat(this.y, 4);
}
},
//曲线的示例说明,像地图上得图标说明一样
legend: {
enabled: true
},
//把曲线图导出成图片等格式
exporting: {
enabled: true
},
//放入数据
series: [
{
name: 'CPU使用率',
data: (function() {
// 初始化数据
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i++) {
data.push({
x: time + i * 1000,
y: Math.random() * 100
});
}
return data;
})()
}
]
});
getCpuInfo();
});
function getCpuInfo(){
$.ajax({
url: "GetCpu",
type: "post",
dataType:'json',
success: function(data){
chart.series[0].addPoint([data.x,data.y], true, true);
}
});
}
setInterval(getCpuInfo, 1000);
</script>
</head>
<body>
<script src="js/highcharts.js"></script>
<script src="js/exporting.js"></script>
<div id="container" style="min- 400px; height: 400px; margin: 0 auto"></div>
</body>
</html>
package com.highcharts.action;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import com.highcharts.dao.SnmpGetAsyn;
public class GetCpu extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String ip = "219.230.155.67";
String community = "public";
List<String> oidList = new ArrayList<String>();
//ssCpuRawUser
oidList.add(".1.3.6.1.4.1.2021.11.50.0");
//ssCpuRawNice
oidList.add(".1.3.6.1.4.1.2021.11.51.0");
//ssCpuRawSystem
oidList.add(".1.3.6.1.4.1.2021.11.52.0");
//ssCpuRawIdle
oidList.add(".1.3.6.1.4.1.2021.11.53.0");
//ssCpuRawWait
oidList.add(".1.3.6.1.4.1.2021.11.54.0");
//ssCpuRawKernel
//oidList.add(".1.3.6.1.4.1.2021.11.55.0");
//ssCpuRawInterrupt
oidList.add(".1.3.6.1.4.1.2021.11.56.0");
//ssCpuRawSoftIRQ
oidList.add("1.3.6.1.4.1.2021.11.61.0");
// 异步采集数据
List cpuData = SnmpGetAsyn.snmpAsynGetList(ip, community, oidList);
double ssCpuRawUser = Double.parseDouble(cpuData.get(0).toString());
double ssCpuRawNice = Double.parseDouble(cpuData.get(1).toString());
double ssCpuRawSystem = Double.parseDouble(cpuData.get(2).toString());
double ssCpuRawIdle = Double.parseDouble(cpuData.get(3).toString());
double ssCpuRawWait = Double.parseDouble(cpuData.get(4).toString());
double ssCpuRawInterrupt = Double.parseDouble(cpuData.get(5).toString());
double ssCpuRawSoftIRQ = Double.parseDouble(cpuData.get(6).toString());
Map<String, Object> jsonMap = new HashMap<String, Object>();//定义map
double cpuRatio = 100*(ssCpuRawUser+ssCpuRawNice+ssCpuRawSystem+ssCpuRawWait+ssCpuRawInterrupt+ssCpuRawSoftIRQ)/(ssCpuRawUser+ssCpuRawNice
+ssCpuRawSystem+ssCpuRawIdle+ssCpuRawWait+ssCpuRawInterrupt+ssCpuRawSoftIRQ);
System.out.println("CPU利用率:"+cpuRatio);
jsonMap.put("y",cpuRatio);
jsonMap.put("x", new Date().getTime());
JSONObject result = JSONObject.fromObject(jsonMap);//格式化result 一定要是JSONObject
out.print(result.toString());
out.flush();
out.close();
}
}
package com.highcharts.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.event.ResponseListener;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
/**
* 演示:异步GET OID值
*
* blog http://www.micmiu.com
*
* @author Michael
*
*/
public class SnmpGetAsyn {
public static final int DEFAULT_VERSION = SnmpConstants.version2c;
public static final String DEFAULT_PROTOCOL = "udp";
public static final int DEFAULT_PORT = 161;
public static final long DEFAULT_TIMEOUT = 3 * 1000L;
public static final int DEFAULT_RETRY = 3;
/**
* 创建对象communityTarget
*
* @param targetAddress
* @param community
* @param version
* @param timeOut
* @param retry
* @return CommunityTarget
*/
public static CommunityTarget createDefault(String ip, String community) {
Address address = GenericAddress.parse(DEFAULT_PROTOCOL + ":" + ip
+ "/" + DEFAULT_PORT);
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString(community));
target.setAddress(address);
target.setVersion(DEFAULT_VERSION);
target.setTimeout(DEFAULT_TIMEOUT); // milliseconds
target.setRetries(DEFAULT_RETRY);
return target;
}
/**
* 异步采集信息
*
* @param ip
* @param community
* @param oid
*/
public static List snmpAsynGetList(String ip, String community,
List<String> oidList) {
final List cpuData = new ArrayList();
CommunityTarget target = createDefault(ip, community);
Snmp snmp = null;
try {
DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
snmp = new Snmp(transport);
snmp.listen();
PDU pdu = new PDU();
for (String oid : oidList) {
pdu.add(new VariableBinding(new OID(oid)));
}
final CountDownLatch latch = new CountDownLatch(1);
ResponseListener listener = new ResponseListener() {
public void onResponse(ResponseEvent event) {
((Snmp) event.getSource()).cancel(event.getRequest(), this);
PDU response = event.getResponse();
PDU request = event.getRequest();
System.out.println("[request]:" + request);
if (response == null) {
System.out.println("[ERROR]: response is null");
} else if (response.getErrorStatus() != 0) {
System.out.println("[ERROR]: response status"
+ response.getErrorStatus() + " Text:"
+ response.getErrorStatusText());
} else {
System.out.println("Received response Success!");
for (int i = 0; i < response.size(); i++) {
VariableBinding vb = response.get(i);
/* System.out.println(vb.getOid() + " = "
+ vb.getVariable());*/
cpuData.add(vb.getVariable());
}
System.out.println("SNMP Asyn GetList OID finished. ");
latch.countDown();
}
}
};
pdu.setType(PDU.GET);
snmp.send(pdu, target, null, listener);
System.out.println("asyn send pdu wait for response...");
boolean wait = latch.await(30, TimeUnit.SECONDS);
System.out.println("latch.await =:" + wait);
snmp.close();
} catch (Exception e) {
e.printStackTrace();
System.out.println("SNMP Asyn GetList Exception:" + e);
}
return cpuData;
}
public static void main(String[] args) {
String ip = "219.230.155.67";
String community = "public";
List<String> oidList = new ArrayList<String>();
//ssCpuRawUser
oidList.add(".1.3.6.1.4.1.2021.11.50.0");
//ssCpuRawNice
oidList.add(".1.3.6.1.4.1.2021.11.51.0");
//ssCpuRawSystem
oidList.add(".1.3.6.1.4.1.2021.11.52.0");
//ssCpuRawIdle
oidList.add(".1.3.6.1.4.1.2021.11.53.0");
//ssCpuRawWait
oidList.add(".1.3.6.1.4.1.2021.11.54.0");
//ssCpuRawInterrupt
oidList.add(".1.3.6.1.4.1.2021.11.56.0");
//ssCpuRawSoftIRQ
oidList.add("1.3.6.1.4.1.2021.11.61.0");
// 异步采集数据
List cpuData = SnmpGetAsyn.snmpAsynGetList(ip, community, oidList);
double ssCpuRawUser = Double.parseDouble(cpuData.get(0).toString());
double ssCpuRawNice = Double.parseDouble(cpuData.get(1).toString());
double ssCpuRawSystem = Double.parseDouble(cpuData.get(2).toString());
double ssCpuRawIdle = Double.parseDouble(cpuData.get(3).toString());
double ssCpuRawWait = Double.parseDouble(cpuData.get(4).toString());
double ssCpuRawInterrupt = Double.parseDouble(cpuData.get(5).toString());
double ssCpuRawSoftIRQ = Double.parseDouble(cpuData.get(6).toString());
double cpuRatio = 100*(ssCpuRawUser+ssCpuRawNice+ssCpuRawSystem+ssCpuRawWait+ssCpuRawInterrupt+ssCpuRawSoftIRQ)/(ssCpuRawUser+ssCpuRawNice
+ssCpuRawSystem+ssCpuRawIdle+ssCpuRawWait+ssCpuRawInterrupt+ssCpuRawSoftIRQ);
System.out.println("CPU利用率:"+cpuRatio);
}
}
浏览器访问:http://localhost:8080/HighChartTest/highChartsTest.jsp
效果如图(截取一个静态的图):
至此,基本的效果已经出来,但是还有些地方需要完善。
一、cpu的利用率的计算方法需要改变:
1、 采样两个足够短的时间间隔的Cpu快照,分别记作t1,t2,其中t1、t2的结构均为:
(user、nice、system、idle、iowait、irq、softirq、stealstolen、guest)的9元组;
2、 计算总的Cpu时间片totalCpuTime
a) 把第一次的所有cpu使用情况求和,得到s1;
b) 把第二次的所有cpu使用情况求和,得到s2;
c) s2 - s1得到这个时间间隔内的所有时间片,即totalCpuTime = j2 - j1 ;
3、计算空闲时间idle
idle对应第四列的数据,用第二次的第四列 - 第一次的第四列即可
idle=第二次的第四列 - 第一次的第四列
6、计算cpu使用率
pcpu =100* (total-idle)/total
二、代码需要重构
ps:这个demo多有不足之处,望指出。完善版的以后奉上。