10min 手寫一個內存監控系統
本文的目的在於,儘可能用簡單的代碼,讓大家了解內存監控的原理,及思想。更容易去理解Nagios、Zabbix、Ganglia監控原理,文章最後還有視頻教程哦,從零敲出來的全過程
思路分為下面幾塊:
- 獲取內存監控信息
- 存儲監控信息
- 數據展現
- 後續擴展
- 加主機名,monitor部署在多台機器,不直接插入資料庫
- 增加CPU,Disk監控
- 通過HTTP請求的方式,啟用一個單獨的Flask專門存儲monitor數據
思路圖:
第一步:獲取內存信息
我們通過讀取 /proc/meminfo獲取監控數據MemTotal、MemFree、Buffers、Cached,咱們常用free -m 其實也是讀取的/pro/meminfo的數據,順便說一下
對於操作系統來說,Buffers、Cached是已經被使用的
MemFree=total-used
對於應用程序來說
MemFree=buffers+cached+free
監控物理內存使用
內存使用=MemTotal-MemFree-Buffers-Cached
開擼:monitor.py獲取監控數據
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-cacheprint mem_use/1024while True:time.sleep(1)getMem()
測試:每秒列印一條數據
[www.51reboot.com@teach memory]$ python mointor.py 29202919291929192919
希望內存多變好一些,寫了一個很挫的測試代碼
# test.pys = www.51reboot.com*1000000for i in s:for j in s:s.count(j)
執行python test.py,會發現內存佔用多了幾M,說明咱們的代碼是OK的
第二步:存儲監控信息(我們用MySQL)
我們需要兩個欄位,內存和時間 sql呼之欲出,簡單粗暴
create database memory;create memory(memory int,time int)
接下來我們把monitor.py的數據存儲到資料庫中,這用到了Python MySQLdb模塊
import timeimport MySQLdb as mysqldb = 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-cachet = int(time.time())sql = insert into memory (memory,time) value (%s,%s)%(mem_use/1024,t)cur.execute(sql)print mem_use/1024while True:time.sleep(1)getMem()
暫時告一段落
第三步:數據展現(Flask框架)
代碼結構
├── flask_web.py web後端代碼├── mointor.py 監控數據獲取├── static 靜態文件,第三方圖表庫│ ├── exporting.js│ ├── highstock.js│ └── jquery.js├── templates│ └── index.html 展示前端頁面└── test.py 佔用內存的測試代碼
flask_web.py的代碼如下
提供兩個路由根目錄渲染文件index.html/data路由去資料庫查數據,返回json,供畫圖使用
from flask import Flask,render_template,requestimport MySQLdb as mysqlcon = 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 memorycur.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
<div id="container" stylex="height: 400px; min-width: 310px"></div><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>
執行python flask_web.py,瀏覽器看數據http://www.51reboot.com:9092,出圖了
我們並不僅限於此,如果想實時的看到內存,應該怎麼搞
- 查詢數據時候增加一個時間戳當限制條件,只返回兩次查詢之間的增量數據
- 前端動態添加增量結點數據到圖表中
修改flask_web.py
tmp_time = 0@app.route(/data)def data():global tmp_timeif tmp_time>0:sql = select * from memory where time>%s % (tmp_time/1000)else:sql = select * from memorycur.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秒查一次增量數據,根據自己需求調整,修改index.html
$.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! 效果
後邊改了這麼多,大家可能糊塗了,現在給出完整代碼:
完整代碼大家可以從Github下載
https://github.com/shengxinjing/my_blog/issues/1
視頻下載地址:http://pan.baidu.com/s/1i4acpP7
推薦閱讀:
※python把一個unicode字元串寫入文件為什麼會報錯?
※【精心解讀】關於Jupyter Notebook的28個技巧
※在windows7中python3.4下如何升級pip?
※真正的遠方,到底在哪裡?
※Scrapy對接Splash
TAG:Python |