運維高手十分鐘寫了一個內存監(jiān)控系統(tǒng)
本文的目的在于,盡可能用簡單的代碼,讓大家了解內存監(jiān)控的原理及思想,更容易去理解Nagios、Zabbix、Ganglia監(jiān)控原理。文章***還有視頻教程哦!從零敲出來的全過程。
思路分為下面幾塊:
1.獲取內存監(jiān)控信息
2.存儲監(jiān)控信息
3.數(shù)據(jù)展現(xiàn)
4.后續(xù)擴展
a.加主機名,monitor部署在多臺機器,不直接插入數(shù)據(jù)庫
b.增加CPU,Disk監(jiān)控
c.通過HTTP請求的方式,啟用一個單獨的Flask專門存儲monitor數(shù)據(jù)
思路圖:
***步:獲取內存信息
我們通過讀取 /proc/meminfo獲取監(jiān)控數(shù)據(jù)MemTotal、MemFree、Buffers、Cached,咱們常用free -m 其實也是讀取的/pro/meminfo的數(shù)據(jù),順便說一下。
對于操作系統(tǒng)來說,Buffers、Cached是已經被使用的。
MemFree=total-used
對于應用程序來說:
MemFree=buffers+cached+free
監(jiān)控物理內存使用:
內存使用=MemTotal-MemFree-Buffers-Cached
開擼:monitor.py獲取監(jiān)控數(shù)據(jù)。
- 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()
測試:每秒打印一條數(shù)據(jù)。
- [www.51reboot.com@teach memory]$ python mointor.py 2920
- 2919
- 2919
- 2919
- 2919
希望內存多變好一些,寫了一個很挫的測試代碼。
- # test.py
- s = 'www.51reboot.com'*1000000
- for i in s:
- for j in s:
- s.count(j)
執(zhí)行python test.py,會發(fā)現(xiàn)內存占用多了幾M,說明咱們的代碼是OK的。
第二步:存儲監(jiān)控信息(我們用MySQL)
我們需要兩個字段,內存和時間 sql呼之欲出,簡單粗暴!
- create database memory;
- create memory(memory int,time int)
接下來,我們把monitor.py的數(shù)據(jù)存儲到數(shù)據(jù)庫中,這用到了Python MySQLdb模塊。
- 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
- while True:
- time.sleep(1)
- getMem()
暫時告一段落。
第三步:數(shù)據(jù)展現(xiàn)(Flask框架)
代碼結構:
├── flask_web.py web后端代碼
├── mointor.py 監(jiān)控數(shù)據(jù)獲取
├── static 靜態(tài)文件,第三方圖表庫
│ ├── exporting.js
│ ├── highstock.js
│ └── jquery.js
├── templates
│ └── index.html 展示前端頁面
└── test.py 占用內存的測試代碼
flask_web.py的代碼如下:
提供兩個路由。
◆根目錄渲染文件index.html。
◆/data路由去數(shù)據(jù)庫查數(shù)據(jù),返回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)
#p#
前端index.html
- <div id="container" style="height: 400px; min-width: 310px"></div>
- <script>
- $(function () {
- // 使用當前時區(qū),否則東八區(qū)會差八個小時
- Highcharts.setOptions({
- global: {
- useUTC: false
- }
- });
- $.getJSON('/data', function (data) {
- // Create the chart
- $('#container').highcharts('StockChart', {
- rangeSelector : {
- selected : 1
- },
- title : {
- text : '內存數(shù)據(jù)'
- },
- series : [{
- name : '本機內存',
- data : data,
- tooltip: {
- valueDecimals: 2
- }
- }]
- });
- });
- });
- </script>
執(zhí)行python flask_web.py,瀏覽器看數(shù)據(jù)www.51reboot.com:9092,出圖了。
我們并不僅限于此,如果想實時的看到內存,應該怎么搞?
1.查詢數(shù)據(jù)時候增加一個時間戳當限制條件,只返回兩次查詢之間的增量數(shù)據(jù)。
2.前端動態(tài)添加增量結點數(shù)據(jù)到圖表中。
修改flask_web.py。
- 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秒查一次增量數(shù)據(jù),根據(jù)自己需求調整,修改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!效果。
后邊改了這么多,大家可能糊涂了,現(xiàn)在給出完整代碼:
完整代碼大家可以從Github下載
https://github.com/shengxinjing/my_blog/issues/1
視頻下載地址:http://pan.baidu.com/s/1i4acpP7
錄屏的時候網出問題了,所以錄了兩個:
在線視頻1
在線視頻2