简易的内存监控系统

本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客

文章github源地址,还可以看到具体的代码,喜欢请在原链接右上角加个star

腾讯视频链接

录制中间网出问题了,重启了一下,所以有两部分

本文的目的在于,尽可能用简单的代码,让大家了解内存监控的原理

主题思路

  • 获取内存信息
  • 存储信息
  • 展现
  • 后续扩展
    • 加主机名,monitor部署在多台机器,不直接插数据库
    • 通过http请求的方式,一台机器起flask专门存数据monitor

思路图

第一步,我们需要获取内存信息

其实所有的监控项,包括内存数据,都是从文件中读取的,大家执行以下 cat /proc/meminfo就可以看到关于内存的信息,我们关注的是前四行,总内存,空闲内存,缓冲和缓存大小

计算内存占用量公式:

(总内存-空闲内存-缓冲-缓存)/1024Mb

代码呼之欲出 monitor.py

用with打开文件,可以自动关闭,比直接open优雅那么一丢丢


def getMem():
with open('/proc/meminfo') as f:
total = int(f.readline().split()[1])
free = int(f.readline().split()[1])
buffers = int(f.readline().split()[1])
cache = int(f.readline().split()[1])
mem_use = total-free-buffers-cache
print mem_use/1024
while True:
time.sleep(1)
getMem()

执行文件 python monitor.py,每一秒打印一条内存信息

[woniu@teach memory]$ python mointor.py
2920
2919
2919
2919
2919

我们可以写个很搓的测试代码,占用一点内存,看看数据会不会变

执行下面代码,能看到内存使用量明显多了几M

# test.py

s = 'akdsakjhdjkashdjkhasjkdhasjkdhkjashdaskjhfoopnnm,ioqouiew'*100000

for i in s:
for j in s:
s.count(j)

获取内存数据done!

第二步存储数据库

我们选用mysql

新建表格,我们需要两个字段,内存和时间 sql呼之欲出,简单粗暴

create memory(memory int,time int)

我们的 monitor.py就不能只打印内存信息了,要存储数据库啦,引入mysql模块,代码如下

import time
import MySQLdb as mysql db = mysql.connect(user="reboot",passwd="reboot123",db="memory",host="localhost")
db.autocommit(True)
cur = db.cursor() def getMem():
with open('/proc/meminfo') as f:
total = int(f.readline().split()[1])
free = int(f.readline().split()[1])
buffers = int(f.readline().split()[1])
cache = int(f.readline().split()[1])
mem_use = total-free-buffers-cache
t = int(time.time())
sql = 'insert into memory (memory,time) value (%s,%s)'%(mem_use/1024,t)
cur.execute(sql)
print mem_use/1024
#print 'ok'
while True:
time.sleep(1)
getMem()

比之前的多了拼接sql和执行的步骤,具体过程见视频,大家到数据库里执行一下下面的sql,就能看到我们辛辛苦苦获取的内存数据啦

    select * from memory

我们的数据库里数据越来越多,怎么展示呢

我们需要flask

我们看下文件结构

.
├── flask_web.py web后端代码
├── mointor.py 监控数据获取
├── static 静态文件,第三方图表库
│   ├── exporting.js
│   ├── highstock.js
│   └── jquery.js
├── templates
│   └── index.html 展示前端页面
└── test.py 占用内存的测试代码

flask_web就是我们的web服务代码,template下面的html,就是前端展示的文件,static下面是第三方库

flask_web的代码如下

  • 提供两个路由

    • 根目录渲染文件index.html
    • /data路由去数据库插数据,返回json,供画图使用
from flask import Flask,render_template,request
import MySQLdb as mysql con = mysql.connect(user='reboot',passwd='reboot123',host='localhost',db='memory') con.autocommit(True)
cur = con.cursor()
app = Flask(__name__)
import json @app.route('/')
def index():
return render_template('index.html') @app.route('/data')
def data():
sql = 'select * from memory'
cur.execute(sql)
arr = []
for i in cur.fetchall():
arr.append([i[1]*1000,i[0]])
return json.dumps(arr) if __name__=='__main__':
app.run(host='0.0.0.0',port=9092,debug=True)

前端index.html

highstock的demo页面,copy过来,具体过程见视频

<html>
<head>
<title>51reboot</title>
</head> <body>
hello world <div id="container" style="height: 400px; min-width: 310px"></div> <script src='/static/jquery.js'></script>
<script src='/static/highstock.js'></script>
<script src='/static/exporting.js'></script>
<script>
$(function () {
// 使用当前时区,否则东八区会差八个小时
Highcharts.setOptions({
global: {
useUTC: false
}
});
$.getJSON('/data', function (data) {
// Create the chart
$('#container').highcharts('StockChart', {
rangeSelector : {
selected : 1
},
title : {
text : '内存数据'
},
series : [{
name : '本机内存',
data : data,
tooltip: {
valueDecimals: 2
}
}]
});
});
});
</script>
</body>
</html>

具体观察数据结构的过程,见视频和demo链接,我们做的 就是把数据库里的数据,拼接成前端画图需要的数据,展现出来

这时候前端就能看到图表啦

我们并不仅限于此,如果想实时的看到内存,应该怎么搞呢

  • 查询数据时候增加一个时间戳当限制条件,再次查询时,只返回两次查询之间的增量数据
  • 前端动态添加增量结点数据到图表中
  • 代码呼之欲出

python


tmp_time = 0 @app.route('/data')
def data():
global tmp_time
if tmp_time>0:
sql = 'select * from memory where time>%s' % (tmp_time/1000)
else:
sql = 'select * from memory'
cur.execute(sql)
arr = []
for i in cur.fetchall():
arr.append([i[1]*1000,i[0]])
if len(arr)>0:
tmp_time = arr[-1][0]
return json.dumps(arr)

前端,3秒查一次增量数据

    $.getJSON('/data', function (data) {

        // Create the chart
$('#container').highcharts('StockChart', {
chart:{
events:{
load:function(){
var series = this.series[0]
setInterval(function(){
$.getJSON('/data',function(res){
$.each(res,function(i,v){
series.addPoint(v)
})
})
},3000)
}
}
},
rangeSelector : {
selected : 1
},
title : {
text : 'AAPL Stock Price'
},
series : [{
name : 'AAPL',
data : data,
tooltip: {
valueDecimals: 2
}
}]
});
});

done!两个文件都搞定,double kill!

效果

最终代码直接下载那个木看也行

监控文件monitor.py

import time
import MySQLdb as mysql db = mysql.connect(user="reboot",passwd="reboot123",db="memory",host="localhost")
db.autocommit(True)
cur = db.cursor() def getMem():
with open('/proc/meminfo') as f:
total = int(f.readline().split()[1])
free = int(f.readline().split()[1])
buffers = int(f.readline().split()[1])
cache = int(f.readline().split()[1])
mem_use = total-free-buffers-cache
t = int(time.time())
sql = 'insert into memory (memory,time) value (%s,%s)'%(mem_use/1024,t)
cur.execute(sql)
print mem_use/1024
#print 'ok'
while True:
time.sleep(1)
getMem()

flask

from flask import Flask,render_template,request
import MySQLdb as mysql con = mysql.connect(user='reboot',passwd='reboot123',host='localhost',db='memory')
con.autocommit(True)
cur = con.cursor()
app = Flask(__name__)
import json @app.route('/')
def index():
return render_template('index.html') tmp_time = 0 @app.route('/data')
def data():
global tmp_time
if tmp_time>0:
sql = 'select * from memory where time>%s' % (tmp_time/1000)
else:
sql = 'select * from memory'
cur.execute(sql)
arr = []
for i in cur.fetchall():
arr.append([i[1]*1000,i[0]])
if len(arr)>0:
tmp_time = arr[-1][0]
return json.dumps(arr) if __name__=='__main__':
app.run(host='0.0.0.0',port=9092,debug=True)

前端

<html>
<head>
<title>51reboot</title>
<meta charset='utf-8'>
</head> <body>
hello world <div id="container" style="height: 400px; min-width: 310px"></div> <script src='/static/jquery.js'></script>
<script src='/static/highstock.js'></script>
<script src='/static/exporting.js'></script>
<script>
$(function () {
// 使用当前时区,否则东八区会差八个小时
Highcharts.setOptions({
global: {
useUTC: false
}
});
$.getJSON('/data', function (data) { // Create the chart
$('#container').highcharts('StockChart', {
chart:{
events:{ load:function(){ var series = this.series[0]
setInterval(function(){
$.getJSON('/data',function(res){
$.each(res,function(i,v){
series.addPoint(v)
})
})
},3000)
}
}
}, rangeSelector : {
selected : 1
}, title : {
text : '内存数据'
}, series : [{
name : '本机内存',
data : data,
tooltip: {
valueDecimals: 2
}
}]
});
}); });
</script> </body>
</html>

代码没有特别注意细节,希望大家喜欢。


最后 github原地址继续求star哇

https://github.com/shengxinjing/my_blog/issues/1

用python 10min手写一个简易的实时内存监控系统的更多相关文章

  1. [转]用python 10min手写一个简易的实时内存监控系统

    简易的内存监控系统 本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客 文章github源地址,还可以看到具体的代码,喜欢请在原链接右上角加个star 腾讯视频链接 ...

  2. 10min 手写一个内存监控系统

    本文的目的在于,尽可能用简单的代码,让大家了解内存监控的原理,及思想.更容易去理解Nagios.Zabbix.Ganglia监控原理,文章最后还有视频教程链接哦,从零敲出来的全过程 思路分为下面几块: ...

  3. 手写一个简易的IOC

    这个小项目是我读过一点Spring的源码后,模仿Spring的IOC写的一个简易的IOC,当然Spring的在天上,我写的在马里亚纳海沟,哈哈 感兴趣的小伙伴可以去我的github拉取代码看着玩 地址 ...

  4. 来,我们手写一个简易版的mock.js吧(模拟fetch && Ajax请求)

    预期的mock的使用方式 首先我们从使用的角度出发,思考编码过程 M1. 通过配置文件配置url和response M2. 自动检测环境为开发环境时启动Mock.js M3. mock代码能直接覆盖g ...

  5. 手写一个简易的多周期 MIPS CPU

    一点前言 多周期 CPU 相比单周期 CPU 以及流水线 CPU 实现来说其实写起来要麻烦那么一些,但是相对于流水线 CPU 和单周期 CPU 而言,多周期 CPU 除了能提升主频之外似乎并没有什么卵 ...

  6. 手写一个简易版Tomcat

    前言 Tomcat Write MyTomcat Tomcat是非常流行的Web Server,它还是一个满足Servlet规范的容器.那么想一想,Tomcat和我们的Web应用是什么关系? 从感性上 ...

  7. 手写一个虚拟DOM库,彻底让你理解diff算法

    所谓虚拟DOM就是用js对象来描述真实DOM,它相对于原生DOM更加轻量,因为真正的DOM对象附带有非常多的属性,另外配合虚拟DOM的diff算法,能以最少的操作来更新DOM,除此之外,也能让Vue和 ...

  8. 我手写的简易tomcat

    前述 自己手写的简易的tomcat,实现了tomcat的基本响应功能,项目代码已经上传到我的Github,刚刚开始学习这里,当前还存在很多问题 项目简述及代码 当我们的Web运行的时候,从浏览器发出的 ...

  9. 摊牌了!我要手写一个“Spring Boot”

    目前的话,已经把 Spring MVC 相关常用的注解比如@GetMapping .@PostMapping .@PathVariable 写完了.我也已经将项目开源出来了,地址:https://gi ...

随机推荐

  1. C# IL 指令集

    跳转指令集合 Public field Static     Beq     如果两个值相等,则将控制转移到目标指令.Public field Static     Beq_S     如果两个值相等 ...

  2. iOS的推送机制APNs:本地推送&远程推送

    本地推送: 本地推送主要应用在备忘录,闹钟等本地的,基于时间定时的消息提醒.本篇不做详细描述. 远程推送:APNS(苹果推送通知服务) iOS远程推送机制的原理及流程: 注册推送(橙色部分):若该Ap ...

  3. 使用fastcgi_cache加速网站

    为了提高网站的性能缓存是一把利器,nginx中可以配置fastcig_cache来缓存不需要实时获取的数据实现动静分离,nginx.conf配置如下: http {     -     fastcgi ...

  4. Invalid signature file digest for Manifest main attributes

    Solving a Spark error: Invalid signature file digest for Manifest main attributes When using spark-s ...

  5. 关于用自带摄像机录像无法捕获uri 问题解决

    这个 我自己调用,好像并没有出现什么问题. 下面是我的代码.你们可以参照一下 File file = new File(Environment.getExternalStorageDirectory( ...

  6. Ubuntu安装JDK(tar.gz)

    如果没有创建root用户: sudo passwd root 在oracle官网下载jdk(百度"JDK")的tar.gz包: jdk-7u55-linux-x64.gz 这是我下 ...

  7. Python核心编程笔记---- print

    在仅用变量名时,输出的字符串是用单引号括起来的.这个是为了让非字符串对象也可能以字符的形式显示在屏幕上. 而print 函数打印出来的是变量的值. print 调用的是str()方法.而仅用变量名时调 ...

  8. MyBitis(iBitis)系列随笔之五:多表(一对多关联查询)

    MyBitis(iBitis)系列随笔之一:MyBitis入门实例 MyBitis(iBitis)系列随笔之二:类型别名(typeAliases)与表-对象映射(ORM) MyBitis(iBitis ...

  9. poj2136---输出特殊图形

    #include <stdio.h> #include <stdlib.h> #include<string.h> ]; int find(int pos,int ...

  10. oracle查看所有表及字段

    oracle表设计 http://blog.csdn.net/lanpy88/article/details/7580820 Oracle查看所有表和字段 获取表: select table_name ...