使用Java编写一个简单的Web的监控系统cpu利用率,cpu温度,总内存大小
原文:http://www.jb51.net/article/75002.htm
这篇文章主要介绍了使用Java编写一个简单的Web的监控系统的例子,并且将重要信息转为XML通过网页前端显示,非常之实用,需要的朋友可以参考下
公司的服务器需要实时监控,而且当用户空间已经满了,操作失败,或者出现程序Exception的时候就需要实时提醒,便于网管和程序员调式,这样就把这个实时监控系统分为了两部分,
第一部分:实时系统监控(cpu利用率,cpu温度,总内存大小,已使用内存大小)
第二部分:实时告警
由于无刷新实时性,所以只能使用Ajax,这里没有用到任何ajax框架,因为调用比较简单
大家知道,由于java的先天不足,对底层系统的调用和操作一般用jni来完成,特别是cpu温度,你在window下是打死用命令行是得不到的, 但由于我们的服务器系统是linux,所以可以不调用jni完全用java的方式来得到系统信息,这里用到了runtime的exec()函数,通过解析 本地命令调用的结果来查询本地信息,
* 取得linux系统下的cpu、内存信息
*
* */
public final class LinuxSystemTool
{
/**
* get memory by used info
*
* @return int[] result
* result.length==4;int[0]=MemTotal;int[1]=MemFree;int[2]=SwapTotal;int[3]=SwapFree;
* @throws IOException
* @throws InterruptedException
*/
public static int [] getMemInfo() throws IOException, InterruptedException
{
File file = new File( "/proc/meminfo" );
BufferedReader br = new BufferedReader( new InputStreamReader(
new FileInputStream(file)));
int [] result = new int [ 4 ];
String str = null ;
StringTokenizer token = null ;
while ((str = br.readLine()) != null )
{
token = new StringTokenizer(str);
if (!token.hasMoreTokens())
continue ; str = token.nextToken();
if (!token.hasMoreTokens())
continue ; if (str.equalsIgnoreCase( "MemTotal:" ))
result[0 ] = Integer.parseInt(token.nextToken());
else if (str.equalsIgnoreCase( "MemFree:" ))
result[1 ] = Integer.parseInt(token.nextToken());
else if (str.equalsIgnoreCase( "SwapTotal:" ))
result[2 ] = Integer.parseInt(token.nextToken());
else if (str.equalsIgnoreCase( "SwapFree:" ))
result[3 ] = Integer.parseInt(token.nextToken());
} return result;
} /**
* get memory by used info
*
* @return float efficiency
* @throws IOException
* @throws InterruptedException
*/
public static float getCpuInfo() throws IOException, InterruptedException
{
File file = new File( "/proc/stat" );
BufferedReader br = new BufferedReader( new InputStreamReader(
new FileInputStream(file)));
StringTokenizer token = new StringTokenizer(br.readLine());
token.nextToken();
int user1 = Integer.parseInt(token.nextToken());
int nice1 = Integer.parseInt(token.nextToken());
int sys1 = Integer.parseInt(token.nextToken());
int idle1 = Integer.parseInt(token.nextToken()); Thread.sleep(1000 ); br = new BufferedReader(
new InputStreamReader( new FileInputStream(file)));
token = new StringTokenizer(br.readLine());
token.nextToken();
int user2 = Integer.parseInt(token.nextToken());
int nice2 = Integer.parseInt(token.nextToken());
int sys2 = Integer.parseInt(token.nextToken());
int idle2 = Integer.parseInt(token.nextToken()); return ( float )((user2 + sys2 + nice2) - (user1 + sys1 + nice1)) / ( float )((user2 + nice2 + sys2 + idle2) - (user1 + nice1 + sys1 + idle1));
}
}
这里的两个方法,解释一下,
方法1文件"/proc/meminfo"里面包含的就是内存的信息,还包括了swap的信息。例如:
$ cat /proc/meminfo total: used: free: shared: buffers: cached:
Mem: 1057009664 851668992 205340672 0 67616768 367820800
Swap: 2146787328 164429824 1982357504
MemTotal: 1032236 kB
MemFree: 200528 kB
MemShared: 0 kB
这样可以用截取字符串的方法,来得到linux内存信息.
方法2在文件"/proc/stat"里面就包含了CPU的信息。每一个CPU的每一tick用在什么地方都在这个文件里面记着。后面的数字含义分 别是: user、nice、sys、idle、iowait。有些版本的kernel没有iowait这一项。这些数值表示从开机到现在,CPU的每tick用 在了哪里。例如:
cpu0 256279030 0 11832528 1637168262
就是cpu0从开机到现在有 256279030 tick用在了user消耗,11832528用在了sys消耗。所以如果想计算单位时间(例如1s)里面CPU的负载,那只需要计算1秒前后数值的差除以每一秒的tick数量就可以了。
ok这样还剩下cpu温度,怎么做呢
发现了一个文件"cat /proc/acpi/thermal_zone/THM/temperature";可以返回本机的linux温度,
大概是这样的:
temperature: 68C
但不是每台linux机器都有这个THM你要确定你的linux加载了这个THM才能使用这个文件,这样就用InputStreamReader(new FileInputStream(new File("/proc/acpi/thermal_zone/THM/temperature")), 去读取这个文件,后面的相信大家一定会做了吧,就是把内容读出来,然后分割字符串去得到这个68。ok,系统基本信息全部完成,然后ok现在就只有一件事就是用Ajax去调用这个类来得到 基本信息,然后返回到页面上,Ajax的用法就不赘言了。
下面是系统监控的效果,大概是Ajax每几秒去linux下去取一次系统信息,然后显示在jsp页面上,以下是效果。
到这里第一部分系统监控部分已经完成,现在开始完成实时告警部分,分析需求
1温度和cpu超过额定值需要告警
2用户操作系统失败,用户存储空间不足也需要告警,还有我们公司的业务操作失败告警,如果发生Exception也只能告警,当然要把异常的堆栈的 信息保存在数据库里,我就这样设计如果用户在操作中触发了这些错误,则保存在数据库的告警表里,然后实时监控的再取出来这些信息。
3告警是要实时的那么要怎么从告警表里查到当前以后的数据呢,一开始想到用当前时间,在当前时间加上Ajax发送时间间隔,select * from warnlist where date>new Date()+AjaxTime这种形式,后来发现时间是很不正确的,网络延迟,程序处理时间,(cpu信息用了sleep函数),等等你常常会发现有些 告警信息被无情的放过,而有的时候有重复数据,这样我想到了用id,每次进入告警系统先查询到最大的告警id,然后保存在session中,然后ajax 从数据库里取告警信息的时候都查这个id之后的数据(就是进入监控系统后的最新数据),然后session再保存新的最大id,下次ajax取还是从这个 session中取最大id,这样信息就可以当ajax取的时候都保证是最新的,而且没有重复,very good!就这样做了
这样设计了一张告警处理表
CREATE
TABLE
`warnlist` (
`Id`
bigint
(20)
NOT
NULL
auto_increment,
`warnleave` tinyint(2)
NOT
NULL
default
'0'
,//告警级别:告警的严重程度
`fromguy`
varchar
(20)
NOT
NULL
,//属于哪个用户哪个组织的告警
`warncontent`
varchar
(100)
NOT
NULL
,//告警内容,比如cpu使用率超过80%
`aviliablevalue`
varchar
(12)
default
NULL
,//允许值 比如85%
`warnvalue`
varchar
(12)
default
NULL
,//告警值 80
`warntime` datetime
NOT
NULL
,//告警时间
`stackinfo`
varchar
(255)
default
NULL
,//异常的堆栈信息
`dealwith` tinyint(2)
NOT
NULL
default
'0'
,//处理结果
`version`
int
(11)
default
NULL
,//version
`organizerID`
varchar
(20)
default
NULL
,//组织id
`des`
varchar
(255)
default
NULL
,
PRIMARY
KEY
(`Id`)
) ENGINE=InnoDB
DEFAULT
CHARSET=utf8;
<
response
>
<
cpuUsed
> 67 </
cpuUsed
>
<
cpuTemp
> 76 <
cpuTemp
>
<
Memory
> 1023422 </
Memory
>
<
freeMemory
> 43244 </
freeMemory
>
<
wannlist
>
<
warnid
> 2 </
warnid
>
<
warncontent
> 系统存储空间不足 </
warncontent
>
<
fromguy
> kakaluyi </
fromguy
>
..............
</
wanrlist
>
<
warnlist
>
<
warnid
> 3 </
warnid
>
<
warncontent
> cpu温度过高 </
warncontent
>
<
fromguy
> 系统 </
fromguy
>
<
orgid
> 系统 </
orgid
>
<
warnvalue
> 78 </
warnvalue
>
.............
</
warnlist
>
........
</
response
>
var
cpuUsed = req .responseXML.getElementsByTagName(
'cpuUsed'
)[0].firstChild.nodeValue;
var
totalMemory = req .responseXML.getElementsByTagName(
'totalMemory'
)[0].firstChild.nodeValue;
var
freeMemory = req .responseXML.getElementsByTagName(
'freeMemory'
)[0].firstChild.nodeValue;
var
cpuTemp = req .responseXML.getElementsByTagName(
'cpuTemp'
)[0].firstChild.nodeValue;
$(
'cpuUsed'
).innerHTML = cpuUsed ;
$(
'totalMemory'
).innerHTML = totalMemory ;
$(
'freeMemory'
).innerHTML = freeMemory ;
$(
'cpuTemp'
).innerHTML = cpuTemp ;
//jsp
< tr >
< td class =
"label"
width =
"20%"
>
</
td
>
<
td
class
=
"text"
>
<
font
color
=
"#FF0000"
size
=
"+2"
> <
label
id
=
"cpuUsed"
> </
label
>
</
font
> < 告警预定阀值: 80% >
</
td
>
</
tr
>
var
length=req.responseXML.getElementsByTagName(
'warnlist'
).length;
if
(length>0)
{
var
trlength=document.getElementsByTagName(
'table'
)[4].childNodes[0].childNodes.length;
if
(trlength+length-1>50)
//如果大于50条,则查找告警列表的table,得到
告警信息的子节点,然后删除多余的最早的告警信息
{
var
tbody=document.getElementsByTagName(
'table'
)[4].childNodes[0];
for
(
var
i=1;i<trlength+length-50;i++)
{
var
tr=tbody.childNodes[i];
tr.parentNode.removeChild(tr);
}
for ( var i=0;i<length;i++)
{
var onewarnlist=req.responseXML.getElementsByTagName( 'warnlist' )[i].childNodes;
if (onewarnlist[0].firstChild.nodeValue==0)
{
var leave= "企业级告警" ;
}
else {
var leave= "运营商级告警" ;
}
var from=onewarnlist[1].firstChild.nodeValue;
var warncontent=onewarnlist[2].firstChild.nodeValue;
var aviliablevalue=onewarnlist[3].firstChild.nodeValue;
var warnvalue=onewarnlist[4].firstChild.nodeValue;
var warntime=onewarnlist[5].firstChild.nodeValue;
var id=onewarnlist[8].firstChild.nodeValue;
if (onewarnlist[6].firstChild.nodeValue==0)
{
var dealwith= "未处理" ;
}
else {
var dealwith= "<font color='red'>已处理</font>" ;
}
var table=document.getElementById( 'warntable' );
var tr=document.createElement( 'tr' );
if (x%2==1)
{
tr.style.backgroundColor="#BFD3F9"
}
else {
tr.style.backgroundColor="#FBFCEB"
}
x++;
table.appendChild(tr);
var td=document.createElement( 'td' );
td.className ='listText' ;
td.innerHTML =x;
tr.appendChild(td);
var td1=document.createElement( 'td' );
td1.className ='listText' ;
td1.innerHTML = leave;
tr.appendChild(td1);
var td2=document.createElement( 'td' );
td2.className ='listText' ;
td2.innerHTML = from;
tr.appendChild(td2);
var td3=document.createElement( 'td' );
td3.className ='listText' ;
td3.innerHTML = warncontent;
tr.appendChild(td3);6
var td4=document.createElement( 'td' );
td4.className ='listText' ;
td4.innerHTML = aviliablevalue;
tr.appendChild(td4);
var td5=document.createElement( 'td' );
td5.className ='listText' ;
td5.innerHTML = '<font color="#FF0000">' +warnvalue+ '</font>' ;
tr.appendChild(td5);
var td6=document.createElement( 'td' );
td6.className ='listText' ;
td6.innerHTML = warntime;
tr.appendChild(td6);
var td7=document.createElement( 'td' );
td7.className ='listText' ;
td7.innerHTML = dealwith;
tr.appendChild(td7);
var td8=document.createElement( 'td' );
td8.className ='listText' ;
td8.innerHTML = id;
tr.appendChild(td8);
}
ok,一切大功告成,以下是最终效果
使用Java编写一个简单的Web的监控系统cpu利用率,cpu温度,总内存大小的更多相关文章
- 编写一个简单的Web Server
编写一个简单的Web Server其实是轻而易举的.如果我们只是想托管一些HTML页面,我们可以这么实现: 在VS2013中创建一个C# 控制台程序 编写一个字符串扩展方法类,主要用于在URL中截取文 ...
- 使用Servlet和JSP实现一个简单的Web聊天室系统
1 问题描述 利用Java EE相关技术实现一个简单的Web聊天室系统,具体要求如下. (1)编写一个登录 ...
- java实现一个简单的Web服务器
注:本段内容来源于<JAVA 实现 简单的 HTTP服务器> 1. HTTP所有状态码 状态码 状态码英文名称 中文描述 100 Continue 继续.客户端应继续其请求 101 Swi ...
- Python学习 - 编写一个简单的web框架(二)
在上一篇日志中已经讨论和实现了根据url执行相应应用,在我阅读了bottle.py官方文档后,按照bottle的设计重写一遍,主要借鉴大牛们的设计思想. 一个bottle.py的简单实例 来看看bot ...
- Python学习 - 编写一个简单的web框架(一)
自己动手写一个web框架,因为我是菜鸟,对于python的一些内建函数不是清楚,所以在写这篇文章之前需要一些python和WSGI的预备知识,这是一系列文章.这一篇只实现了如何处理url. 参考这篇文 ...
- 使用 IDEA 创建 Maven Web 项目 (三)- 编写一个简单的 WEB 应用
编写 Servlet 类 首先,需要在 java 目录下,创建一个名为 org.smart4j.chapter1 的包.然后,在该包下创建一个 HelloServlet 的类,代码如下: packa ...
- 【Java学习笔记】如何写一个简单的Web Service
本Guide利用Eclipse以及Ant建立一个简单的Web Service,以演示Web Service的基本开发过程: 1.系统条件: Eclipse Java EE IDE for Web De ...
- 编写自己的一个简单的web容器(一)
在之前的博客中我更大家说过Http协议是对tcp协议的封装,其底层还是使用tcp协议来进行数据传出的,浏览器实际上就是一个Socket客户端,今天呢我们就开始着手利用ServerSocket来编写一个 ...
- Java入门篇(一)——如何编写一个简单的Java程序
最近准备花费很长一段时间写一些关于Java的从入门到进阶再到项目开发的教程,希望对初学Java的朋友们有所帮助,更快的融入Java的学习之中. 主要内容包括JavaSE.JavaEE的基础知识以及如何 ...
随机推荐
- poj3263 Tallest Cow
题意略去. 考虑给定的R对pair(A, B). 即A能看见B,这意味着B不比A低,并且区间内部的所有元素的高度严格小于A的高度. 我们规定区间的方向:若A > B,为反方向,反之称为正方向. ...
- js的 image 属性 和一个预加载模块
创建一个Image对象:var a=new Image(); 定义Image对象的src: a.src=”xxx.gif”; 这样做就相当于给浏览器缓存了一张图片. 图像对象: 建立图像对 ...
- C#实现随机抽奖和冒泡排序
随机抽奖程序 string[] s = new string[] { "A", "B", "C", "D", " ...
- 通过继承Rect类编写一个具有确定位置的矩形类PlainRect,其确定位置用 矩形的左上角坐标来标识,包含: 添加两个属性:矩形左上角坐标startX和startY。 两个构造方法: 带4个参数的构造方法,用于对startX、startY、width和height属性 初始化; 不带参数的构造方法,将矩形初始化为左上角坐标、长和宽都为0 的矩形; 添加一个方法: 判断某个点是否在矩形内部的方法
package b; public class Rect { Double width; Double height; public Double getWidth() { return width; ...
- 【leetcode❤python】27. Remove Element
#-*- coding: UTF-8 -*- class Solution(object): def removeElement(self, nums, val): "& ...
- block 实现原理(内存管理详解)(二)
在以前,MRC环境下,使用block很可能会出现内存泄漏问题,并且在以往的面试中,一些接触比较久的程序员都会喜欢问到这个问题,block内存泄漏的问题! 下面,我来介绍一下,MRC下Block内存泄漏 ...
- Android 内存溢出解决方案(OOM) 整理总结
在最近做的工程中发现加载的图片太多或图片过大时经常出现OOM问题,找网上资料也提供了很多方法,但自己感觉有点乱,特此,今天在不同型号的三款安卓手机上做了测试,因为有效果也有结果,今天小马就做个详细的总 ...
- 【转载】在Linux中使用VS Code编译调试C++项目
原文:在Linux中使用VS Code编译调试C++项目 最近项目需求,需要在Linux下开发C++相关项目,经过一番摸索,简单总结了一下如何通过VS Code进行编译调试的一些注意事项. 关于VS ...
- TeeChart中 Line的Clear方法
需要注意的是,如果设置了Line.Smoothed=true; 那么调用Clear是无效的,虽然清除了曲线上的点. 但是界面上的曲线,并没有消失. 所以,在每一次Line.Clear();之前,必须确 ...
- Dede CMS 5.5 升级到 5.7 SP1
Dede CMS 5.5 的漏洞实在是太多了,三天两头被Hacker们挂马.话说挂这些破网址真的能带来丰厚的回报吗?做人要厚道啊. 闲话少说,我按照网上的升级到5.5升级到5.7不出错的方法,升级 ...