`
kakaluyi
  • 浏览: 438027 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

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

阅读更多

 

 

公司的服务器需要实时监控,而且当用户空间已经满了,操作失败,或者出现程序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,一切大功告成,以下是最终效果

  • XMLHelper.rar (488 Bytes)
  • 描述: 简单的,生成xml格式文本的类
  • 下载次数: 806
  • LinuxSystemTool.rar (871 Bytes)
  • 描述: 用来获取linux系统信息 ecsun兄的LinuxSystemTool类
  • 下载次数: 889
分享到:
评论
43 楼 danStart 2017-05-08  
想问问,能监测服务是否挂掉吗?
42 楼 leo_dream 2009-01-09  
有没有实时监控网站,监控后台的方法
41 楼 lqql 2009-01-08  
嗯,我们做的监控,要达到300个点以上!用的是JAVA+FLEX.通信用socket
40 楼 阳光晒晒 2009-01-08  
socket多好.30-50个点一台机器...
39 楼 Else 2009-01-08  
以上说的都是监控pc状态的,有没有监控别的参数的,比如我们要监控ATM机的打印机,钞箱,读卡器,用什么技术方案好些,socket,jms?
38 楼 kakaluyi 2008-08-29  
fxbird 写道
kakaluyi 写道
看来大家很少需要做这种实时监控,或者javaeye大牛真的很多,
觉得鄙人做得东东档次太低,不屑给建议,曲低和寡啊。。。

其实大牛也不会,大牛们更喜欢研究开源、框架。

大牛都偏向系统架构那块,这种是雕虫小技了

回上面朋友,大家都趋向于开源,看来自己又造了个轮子,不过我决定参考开源但不完全使用,继续改造这轮子,谁叫这些代码是俺的孩子呢
37 楼 cuiyi.crazy 2008-08-29  
还是尽量的要开源的
一是减少代码量
二是更稳定更可靠
三是更易于升级和扩展
36 楼 fxbird 2008-08-27  
kakaluyi 写道
看来大家很少需要做这种实时监控,或者javaeye大牛真的很多,
觉得鄙人做得东东档次太低,不屑给建议,曲低和寡啊。。。

其实大牛也不会,大牛们更喜欢研究开源、框架。
35 楼 yimlin 2008-08-27  
应该建议公司领导买一个网管软件,一个好的网管软件都能干这事!
34 楼 土匪一份子 2008-08-26  
kakaluyi 写道
回楼上:
因为网管就只有很少的几个人会对服务器进行轮询监控,我觉得服务端压力不会太大,这种情况我倒觉得用推的方式对服务器的压力倒更大,(servlet会独占一个线程)

嘿嘿,楼主 我上个系统也做了这模块,监控10台服务器,方式跟你的差不多,客户端对服务器轮询监控,这块就一两个管理员会用到,服务端的压力没什么影响,页面打开后,AJAX十秒访问一次。
33 楼 lzy.je 2008-08-22  
理解。

看来基本是客户不明白装明白了。
32 楼 kakaluyi 2008-08-22  
lzy.je 写道
用socket吧,c++写比较好:
native code本身对系统消耗低,优势。
想到的方法:
1.通过调用系统命令。管道+正则,这种写起来简单,各个系统平台的命令结果差别是有,不过不是很大。
2.通过系统提供的性能模块。api不是太好找。
3.购买工具,免费开源的也有。开源的最好了,可以改造也,验证下系统利用率,提高采样率还可以用于高采样率的性能测试环境,不过采集数据的保存和可视化就要自己搞了。ganglia就很好,至少可以做base.

不过要是想监控java中间件的,那就要是java了,通过jmx。
oracle或sqlserver监控没搞过,自己想到通过statics view查询,不过这招不知道靠谱不。

如果公司要用底层实现就用不着我了,因为要集成到j2ee的项目里,做一个风格和项目相同的web监控,因为要对客户友好,傻瓜式操作,如果用工具来监控就太没技术含量了(其实恰恰相反),所以没办法自己造轮子了,而且这轮子也就样子好看些,跑久了就爆胎了。。。 
31 楼 lzy.je 2008-08-22  
才看到,上面的兄弟搞到了ganglia,那就说说。
这东西兼容的平台很多,c写的,开源,有aix,solaris,hp-ux,rhel4,5,windows(要用cygwin),验证过它的grid和cluster。架构三部分:gmond,gmated,php web client分别是采集,存储,数据可视化。优点是配置简单,内容也全(不过aix power之外的平台不能采disk read/write),添加自定义的采样不是很容易,就是加上了可用性也不高。更重要的是,在验证时发现(rhel4u4)gmond的内存碎片比较大,猜测可能是由于拼xml造成的(印象里代码中xml是拼成的,3.0.7版)。
不过由于gmond采集是独立的,而且是socket-based的,所以可以裁减ganglia。

另外看到用ganglia的组织挺多的,呵呵,不愧是Berkeley。
30 楼 lzy.je 2008-08-22  
用socket吧,c++写比较好:
native code本身对系统消耗低,优势。
想到的方法:
1.通过调用系统命令。管道+正则,这种写起来简单,各个系统平台的命令结果差别是有,不过不是很大。
2.通过系统提供的性能模块。api不是太好找。
3.购买工具,免费开源的也有。开源的最好了,可以改造也,验证下系统利用率,提高采样率还可以用于高采样率的性能测试环境,不过采集数据的保存和可视化就要自己搞了。ganglia就很好,至少可以做base.

不过要是想监控java中间件的,那就要是java了,通过jmx。
oracle或sqlserver监控没搞过,自己想到通过statics view查询,不过这招不知道靠谱不。
29 楼 lixjluck 2008-08-22  
确实,有些东西不一定 一定要用java实现。
28 楼 kakaluyi 2008-08-22  
MiMiEye 写道
为什么都喜欢搞这么复杂.

直接写个 linux 下的 shell 脚本,实时报告自己的状态至一个数据库;
java端应用直接操作数据库不就得了....

不觉得,按你那样做,既然要实时,服务端就要不停的把状态写入数据库,但是其实他的状态就是不停的写入本地文件与其再写一次数据库不如直接读文件,而且如果像你说的那样做,一次就是读写两次操作数据库了,而且服务器你要不停的写,浏览器客户端而且要不停的读,你怎么保证时钟同步
27 楼 murainwood 2008-08-22  
MiMiEye 写道
为什么都喜欢搞这么复杂.

直接写个 linux 下的 shell 脚本,实时报告自己的状态至一个数据库;
java端应用直接操作数据库不就得了....

不错的主意!
26 楼 MiMiEye 2008-08-21  
为什么都喜欢搞这么复杂.

直接写个 linux 下的 shell 脚本,实时报告自己的状态至一个数据库;
java端应用直接操作数据库不就得了....
25 楼 agen_0502 2008-08-21  
个人感想: 还不如装个SiteScope, 用它来做实时监控是非常不错的一个工具。
24 楼 kakaluyi 2008-08-21  
回楼上:
因为网管就只有很少的几个人会对服务器进行轮询监控,我觉得服务端压力不会太大,这种情况我倒觉得用推的方式对服务器的压力倒更大,(servlet会独占一个线程)

相关推荐

    python-web系统实时监控

    python-flask框架,实时监控本地系统的cpu、内存使用率,用psutil获得系统进程信息,flask web框架,ajax局部刷新获得数据,echarts图表显示,sqlalchemy连接mysql数据库,只要把数据库连接换成自己的就可以用了

    Web服务器运行状态实时监控 v2.0

    远程监控端功能: 监控端可以同时对多台服务器提供的多个服务进行监控,实行多线程管理,可以在远程任何能访问服务器的地方进行实时监控服务器运行状况。可以随意增加、删除、修改需要监控的服务,具有锁定本机桌面...

    基于嵌入式Web服务器的远程视频监控系统

    基于嵌入式Web服务器的远程视频监控系统,希望对家加有所帮助

    Web服务器运行状态实时监控 v2.0.rar

    监控端可以同时对多台服务器提供的多个服务进行监控,实行多线程管理,可以在远程任何能访问服务器的地方进行实时监控服务器运行状况。可以随意增加、删除、修改需要监控的服务,具有锁定本机桌面、重启远程IIS 服务...

    基于以太网和嵌入式Web服务器的监控系统设计

    该系统通过采用嵌入式Web服务器使煤矿生产系统的每个监控子系统均拥有自己独立的Web服务器,采用以太网对监控子系统组网,并通过适当的网关将现场监控网络接入煤矿办公自动化局域网,使现场监控网络和办公自动化网络...

    网络眼睛云服务器监控系统使用教程

    网络眼睛云服务器监控系统使用教程,网络眼睛服务器监控软件,网络眼睛服务器监控工具,软件功能介绍: Cpu利用率监控:当cpu利用率达到设置的警告数值后发送警告信息(可发送邮件或短信),并执行预设的程序。 ...

    云服务器web管理系统

    资源名称:云服务器web管理系统工具简介:web服务器管理软件是最好用的免费Web服务器管理软件,Web服务器环境一键安装,全功能版。实时查看WEB站点的流量、连接数等运行情况和服务器网络带宽占用。快速建站只需输入...

    基于嵌入式Web技术的矿井远程监控系统

    该方案采用ARM920T为内核的S3C2440嵌入式硬件平台,利用实时Linux操作系统作为软件平台,以嵌入式Web服务器为网关实现协议转换和数据的存储转发,达到了矿井远程监控的目的。阐述了网关的硬件设计,重点论述了嵌入式Web...

    Falcon-Web服务器文件监控平台 0.1.1.zip

    Falcon是一款基于inotify-tools开发的Web服务器文件监控平台,能够实时监控Web目录文件变化(新增,修改,删除),判断文件内容是否包含恶意代码,自动隔离常见Webshell,保证Web目录文件安全。 Falcon 0.1.1 更新...

    WEB服务器运行状况监控 v2.1

    可以实时监控您的WEB服务器的运行状况,并将运行数据实时显示在客户端。

    面向远程监控系统的嵌入式web服务器研究与实现

    面向远程监控系统的嵌入式web服务器研究与实现 面向远程监控系统的嵌入式web服务器研究与实现

    基于嵌入式Linux和Web服务器的网络视频监控系统.pdf

    基于嵌入式Linux和Web服务器的网络视频监控系统.pdf

    基于mini6410_tiny6410的WEB远程视频实时监控系统

    基于mini6410_tiny6410的WEB远程视频实时监控系统。源码,实验步骤,开发文档,淘宝资料

    WEB服务器运行状况监控

    搜藏了很久的web服务器监控程序,设定每隔一段时间访问一下网站,如果访问不到,就会发出报警。网站管理很有用的

    基于嵌入式Web服务器的智能温室监控系统

    阐述了一个温室大棚的自动控制系统。该系统使用Luminary公司的LM3S102处理器以及精简的TCP/IP协议栈,构建了嵌入式Web服务器,实现基于以太网的智能温室大棚监控功能。

    面向远程监控系统的嵌入式web 服务器研究与实现

    对嵌入式Web 服务器的通信原理进行了研究,通过分析嵌入式Web ...了一种应用于远程监控系统的嵌入式Web 服务器的实现方案,解决了传统监控系统成本高、搭建复杂、维护管理不 便的问题,促进了视频监控领域网络化的发展

    Falcon-Web服务器文件监控平台 v0.1.1.zip

    Falcon是一款基于inotify-tools开发的Web服务器文件监控平台,能够实时监控Web目录文件变化(新增,修改,删除),判断文件内容是否包含恶意代码,自动隔离常见Webshell,保证Web目录文件安全。   Falcon 0.1.1 ...

    云服务器web管理系统 v3.0

    站点信息监控实时查看WEB站点的流量、连接数等运行情况和服务器网络带宽占用。WebShell实时扫描支持实时或手动查杀各种WebShell木马。扫描速度超快,资源占用极低,并且可以自定义木马特征码。批量替换快速查找文件...

Global site tag (gtag.js) - Google Analytics