標籤:

10min 手寫一個內存監控系統

本文的目的在於,儘可能用簡單的代碼,讓大家了解內存監控的原理,及思想。更容易去理解Nagios、Zabbix、Ganglia監控原理,文章最後還有視頻教程哦,從零敲出來的全過程

思路分為下面幾塊:

  1. 獲取內存監控信息
  2. 存儲監控信息
  3. 數據展現
  4. 後續擴展
    1. 加主機名,monitor部署在多台機器,不直接插入資料庫
    2. 增加CPU,Disk監控
    3. 通過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,瀏覽器看數據51reboot.com:9092出圖了

我們並不僅限於此,如果想實時的看到內存,應該怎麼搞

  1. 查詢數據時候增加一個時間戳當限制條件,只返回兩次查詢之間的增量數據
  2. 前端動態添加增量結點數據到圖表中

修改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下載

github.com/shengxinjing

視頻下載地址:pan.baidu.com/s/1i4acpP


推薦閱讀:

python把一個unicode字元串寫入文件為什麼會報錯?
【精心解讀】關於Jupyter Notebook的28個技巧
在windows7中python3.4下如何升級pip?
真正的遠方,到底在哪裡?
Scrapy對接Splash

TAG:Python |