我们产品线的服务器告警模式是:“每十分钟执行一次脚本,脚本会使用zkclient获取当前服务器的CPU、内存、带宽、服务负载,然后以邮件的形式发送到运维人员的邮箱里”,每十分钟一次的频率可想而知,一天下来邮箱要有几百几千封邮件,看着就心烦。于是我就冒出了一个大胆的想法,重构这套土了吧唧的告警模式。
思路是这样的:“依旧是通过后台脚本结合crontab定时获取服务器的相关采集值,然后将值传入到Django的views.py里,呈现到某个页面上,这个页面也会定时自动刷新,每次刷新的时候也就顺便取到了新的采集值,如果有告警,那么页面对应的告警值红色标注,同时弹出通知。”
这么一看感觉高大上了很多,至少不用天天去outlook里清理垃圾邮件。
实现自动刷新
页面自动刷新的方法很简单,有如下2种:
1.页面自动刷新:把如下代码加入<head>
区域中
1
<meta http-equiv="refresh" content="20"> //其中20指每隔20秒刷新一次页面.
这个功能也能结合页面自动跳转:把如下代码加入<head>
区域中
1
<meta http-equiv="refresh" content="20;url=http://www.webjx.com"> //其中20指隔20秒后跳转到http://www.webjx.com页面
我想,QQ好友生日祝福功能里10秒钟自动关闭就应该是这么做出来的。
2.页面自动刷新之js版
1
2
3
4
5
6<script language="JavaScript">
function myrefresh(){
window.location.reload();
}
setTimeout('myrefresh()',1000); //指定1秒刷新一次
</script>
这里多说一下http-equiv
,http-equiv
是响应头报文。它只能出现在meta
标签里,用来代替name
,它的值使用content
属性描述,HTTP服务器通过此属性收集HTTP协议的响应头报文。
比如:
1
<meta http-equiv="Content-Type" Content="text/html; Charset=gb2312″ />
上面代码告诉浏览器等设备,文件为html文件,且使用了utf8编码;
1
<meta http-equiv="Content-Language" Content="zh-CN" />
上面代码告诉浏览器等设备,语言使用了中文;
1
<meta http-equiv="Expires" Content="Wed, 26 Feb 1997 08:21:57 GMT" />
上面代码指定网页在缓存中的过期时间,一旦网页过期,必须到服务器上重新调阅。注意:必须使用GMT的时间格式,或直接设为0(数字表示多少时间后过期)。
实现桌面通知
桌面通知是一个比较优雅的功能,只要你后台打开网页,那么一旦网页里触发了通知,就会在windows桌面上弹出一个小窗口告诉我们页面发生了,如图:
它的实现关键词就是Notification API
,这个动作的js代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<script type="text/javascript">
//判断浏览器是否支持Notification
if (window.Notification) {
var title;
var options;
title = '服务器告警提醒'; //通知的标题
options = { //通知的所有内容
body: "机器千万台,稳定第一条,服务一瘫痪,运维泪两行。", //通知主体内容
tag: "custom", //代表通知的一个识别标签,相同tag时只会打开同一个通知窗口
icon: "http://img.mp.itc.cn/upload/20160723/a5953dc52c484834ab1ce924bb344da8_th.jpg", //要在通知中显示的图标的URL
// images: "https://xxx.jpg" //要在通知中显示的图像的URL
requireInteraction: false //通知保持自动关闭
};
Notification.requestPermission(function() {
var notification = new Notification(title, options);
notificationEvents.forEach(function(eventName) {
notification[eventName] = function(event) {
};
});
});
} else {
alert("你使用的浏览器不支持弹出提示,请更换Chrome内核浏览器!");
}
</script>
再结合上面的自动刷新语句,在浏览器打开的时候,首先会询问是够接受“通知”,如图:
同意了之后,浏览器每10秒钟自动刷新,同时弹出上面那个加菲猫弹窗。
而且Notification API
只能对https的网站可用,详情可见: https://stackoverflow.com/questions/30542287/are-push-notifications-possible-in-html5-without-fully-https-site 。
全部整合
现在就需要把上面两个功能全部整合到一起,实现每10分钟自动刷新,同时判断传入数值,如果数值超标就发送桌面通知
。
首先,先在django的url.py
里设定访问的路径和对应的函数:
1
2
3
4
5
6
7from django.urls import path
from . import views
urlpatterns = [
# 前面略
path(r'test222/',views.ttt),
]
然后在views.py
里简单设置一下这个ttt
函数:
1
2
3
4
5def ttt(request):
cpu = 6.66
mem = 66.6
disk = 26
return render_to_response('test222.html',{'CPU':cpu,'MEMORY':mem,'DISKUSED':disk})
现在已经传入了三个数值,然后我们加工一下test222.html
页面,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38<html>
<head>
<meta http-equiv="refresh" content="60">
<title>服务器监控页面</title>
<script type="text/javascript">
var cpu="{{CPU}}",mem="{{MEMORY}}",disk="{{DISKUSED}}"
// alert(cpu+' '+mem+' '+disk)
if ( cpu > 80 || mem > 80 || disk > 80) {
if (window.Notification) {
var title;
var options;
title = '服务器告警提醒'; //通知的标题
options = { //通知的所有内容
body: "机器千万台,稳定第一条,服务一瘫痪,运维泪两行。", //通知主体内容 tag: "custom", //代表通知的一个识别标签,相同tag时只会打开同一个通知窗口
icon: "http://img.mp.itc.cn/upload/20160723/a5953dc52c484834ab1ce924bb344da8_th.jpg" //要在通知中显示的图标的URL
};
Notification.requestPermission(function() {
var notification = new Notification(title, options);
notificationEvents.forEach(function(eventName) {
notification[eventName] = function(event) {
};
});
});
} else {
alert("你使用的浏览器不支持弹出提示,请更换Chrome内核浏览器!");
}
}
</script>
</head>
<body>
<h3>服务器名称是test-ooxx-001</h3>
<hr>
<h4>CPU情况是:{{ CPU }}</h4>
<h4>内存情况是:{{ MEMORY }}</h4>
<h4>磁盘容量情况是:{{ DISKUSED }}</h4>
</body>
</html>
界面如下:
现在修改一下views.py
里的三个值,只要有一个大于设定的标准值,就会触发桌面推送。
js里“a=空就判断b,b如果也是空再判断C,然后执行func()”的语句是:
1
2
3if ( a != null || b != null || c != null ) {
fun();
}
参考资料
https://developer.mozilla.org/zh-CN/docs/Web/API/notification
http://www.ptbird.cn/html5-notification-browser.html
https://segmentfault.com/a/1190000011670082