公司的服务器需要实时监控,而且当用户空间已经满了,操作失败,或者出现程序Exception的时候就需要实时提醒,便于网管和程序员调式,这样就把这个实时监控系统分为了两部分,

第一部分:实时系统监控(cpu利用率,cpu温度,总内存大小,已使用内存大小)

第二部分:实时告警

由于无刷新实时性,所以只能使用Ajax,这里没有用到任何ajax框架,因为调用比较简单

大家知道,由于java的先天不足,对底层系统的调用和操作一般用jni来完成,特别是cpu温度,你在window下是打死用命令行是得不到的,但由于我们的服务器系统是linux,所以可以不调用jni完全用java的方式来得到系统信息,这里用到了runtime的exec()函数,通过解析本地命令调用的结果来查询本地信息,

这里要感谢公司同事qinkun推荐ecsun兄的这篇文章http://papa.iteye.com/blog/220532,

* 取得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;

假设我ajax从系统取信息后,那么要写个逻辑,if(cpuTempature>75C)or if(cpuUserd>80%)则写入数据库,然后再查询大于上一次发送Ajax数据库的最大id的告警信息(这期间如果发生的以下错误一并查出:用户存储空间不足,还有我们公司的业务操作失败告警,Exception等),循环插入一个xml解析类中,大概形式是这样的Ajax返回这个xml,供页面提取信息

<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%">
服务器CPU使用率:</td>
<td class="text">
<font color="#FF0000" size="+2"><label id="cpuUsed"></label>
</font> < 告警预定阀值: 80% >
</td>
</tr>.........

然后就是页面展现的问题了这里我用了dom节点的增删,一个页面保持50条记录,如果超过50条则删除以前的节点,代码为:

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,一切大功告成,以下是最终效果

公司要求实时监控服务器,写个Web的监控系统相关推荐

  1. 用Python写一个简单的监控系统

    发表于 2014年9月21日 作者 root 市面上有很多开源的监控系统:Cacti.nagios.zabbix.感觉都不符合我的需求,为什么不自己做一个呢 用Python两个小时徒手撸了一个简易的监 ...

  2. python商品监控系统_Python写的一个简单监控系统

    市面上有很多开源的监控系统:Cacti.nagios.zabbix.感觉都不符合我的需求,为什么不自己做一个呢 用Python两个小时徒手撸了一个简易的监控系统,给大家分享一下,希望能对大家有所启发 ...

  3. 监控服务器时间无法修改怎么办,监控系统时间不对,怎么样修改,谢谢!

    关于摄像头或者监控录像视频修改时间,我曾经在多个论坛或贴吧里回答过这个问题.但是不是说所有摄像头或监控设备都是可以修改时间的.尤其是现在一些网络监控摄像设备,就根本就无法修改时间.但是你可以通过控制台 ...

  4. 【转载】CentsOS系统inotify实时监控服务器文件(夹)定制事件处理程序

    原始博文和参考博文 1.CentsOS系统inotify实时监控服务器文件 2.Linux中让进程在后台运行的方法 3.linux inotify 监控文件系统事件 非常好 方法一 说明: 服务器系统 ...

  5. 自己写的web标准教程,帮你走进web标准设计的世界——第三讲(html终结篇)

    声明:本教程源于本人学习的一些经验的总结,希望大家帮忙完善与指正,也希望会给初学者带来方便,希望大家不要随便转载,写的不是很好,还不完善,不过转载时要注明作者和出处,附加原文的链接地址,谢谢了 已出: ...

  6. 员工工号怎么编码_华为员工感慨:工号就留在这了,感谢公司给我自己写墓志铭的机会...

    前言: 职场就像围城,我们每一个职场人总是以"墙外"的视角羡慕着"墙内"的世界,而也许你的生活也出现在别人的梦中.希望"互联网坊间八卦"能成 ...

  7. 写给 Web 开发者的深度学习教程 - 向量化 矩阵

    前言 在这个科技发展日新月异的时代,行业的宠儿与弃儿就如同手掌的两面,只需轻轻一翻,从业者的境遇便会有天翻地覆的改变. 人工智能作为近两年来业界公认的热门领域,不同于之前火热的移动端开发或前端开发,其 ...

  8. api怎么写_使用Node.js原生API写一个web服务器

    Node.js是JavaScript基础上发展起来的语言,所以前端开发者应该天生就会一点.一般我们会用它来做CLI工具或者Web服务器,做Web服务器也有很多成熟的框架,比如Express和Koa.但 ...

  9. [导入]基于Web的B/S结构实时监控系统[转]

    文章编号:1009-0193(2002)01-0062-02 基于Web的B/S结构实时监控系统 尉学军,刘 跃 (贵州工业大学 电气工程学院,贵州 贵阳 550003) 摘 要:提出了怎样利用Web ...

最新文章

  1. 数据结构三元组实验报告_数据结构实验报告
  2. nodejs安装node-rsa遇到的问题及解决
  3. Java关于文件上传的一个例子
  4. python中定义数据结构_Python中的数据结构—简介
  5. 点击表格弹窗获取另外一套数据之后,原表格相关数据的调用
  6. Magento 安装教程
  7. 英文文本分析:与COVID-19有关的论文文本分析
  8. SqlServer中如何按姓氏笔画排序
  9. 机器学习之K-means算法:深入浅出K-Means算法
  10. 【Windows】win10电脑Miracast投屏到电视
  11. Oracle如何对JDK收费
  12. Android逆向之旅---Android手机端破解神器MT的内购VIP功能破解教程
  13. Android实现VR查看图片
  14. python怎么绘制图例_用Python绘制图例
  15. 【数据技术】关于HP Vertica MPP列式数据库资源池设置的一点心得
  16. HTML——表格的基本样式
  17. 如何治理 Electron 版本淘宝直播应用崩溃?
  18. 车联网上云最佳实践 七
  19. arduino红外热释电传感器_【Arduino】108种传感器系列实验(17)-热释电传感器模块-Arduino中文社区 - Powered by Discuz!...
  20. 解读功利主义——读《渴望崇高》有感2000字

热门文章

  1. SQL-SERVER的STUFF函数group by 分组,字符串合并
  2. ABS故障使用计算机仿真,车辆ABS系统的计算机仿真研究
  3. EPSON1100清零软件 在哪有?
  4. 问题(ArcGIS):去除栅格不需要的Value(背景值0)
  5. P2P之UDP穿透NAT的原理与实现--增强篇(附源代码)
  6. java保姆级教程—— 1.什么是游戏
  7. 学习PCB之pcb器件的绘制
  8. Excel使用攻略(1)
  9. 计算机网络基础(理论知识)
  10. 文件夹的“只读”属性