魔扣论坛

魔扣源码论坛业务
查看: 1336|回复: 5

10min手写一个服务器内存监控系统

[复制链接]

该用户从未签到

5

主题

0

回帖

6

积分

魔扣新手

Rank: 1

魔扣币
6
贡献
6
威望
0
发表于 2016-12-31 16:15:32 | 显示全部楼层 |阅读模式
魔扣币兑换比例:【 50以下 : ¥1 = 10 魔扣币 】丨【 50 - 100 :¥1 = 20 魔扣币】丨【 100以上:¥1 = 30 魔扣币 】

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本文作者shengxinjing (woniuppp) · GitHub ,授权发布
本文需要有一定的Python和前端基础,如果没基础的,请关注我后续的基础教程系列博客
项目地址,可以看到具体的代码,喜欢请加个星星
视频链接

录制中间网出问题了,重启了一下,所以有两部分
本文的目的在于,尽可能用简单的代码,让大家了解内存监控的原理
主题思路

  • 获取内存信息
  • 存储信息
  • 展现
  • 扩展

    • 加主机名,moitor部署在多台机器,不直接插数据库
    • 通过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/1024while True:    time.sleep(1)    getMem()
执行文件 python monitor.py,每一秒打印一条内存信息
[woniu@teach memory]$ python mointor.py 29202919291929192919
我们可以写个很搓的测试代码,占用一点内存,看看数据会不会变
执行下面代码,能看到内存使用量明显多了几M

# test.pys = 'akdsakjhdjkashdjkhasjkdhasjkdhkjashdaskjhfoopnnm,ioqouiew'*100000for i in s:    for j in s:        s.count(j)~                     
获取内存数据done!
第二部存储数据库

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

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

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-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,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 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 timeimport MySQLdb as mysqldb = mysql.connect(user="reboot",passwd="reboot123",db="memory",host="localhost")db.autocommit(True)cur = db.cursor()def getMem():    f = open('/proc/meminfo')    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,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')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>
代码没有特别注意细节,希望大家喜欢
运维开发交流QQ群:238757010

欢迎大家关注公共号,高品质运维开发
本文仅授权51Reboot相关账号发布。

该用户从未签到

1

主题

252

回帖

505

积分

高级魔扣

Rank: 4

魔扣币
252
贡献
252
威望
0
发表于 2017-2-18 14:20:28 | 显示全部楼层
做你最好的朋友,将爱在心底悄悄地掩埋;晨浴甘露,夜伴晚霞,让友谊的花静静地绽开。做你最好的朋友,跳动的脉搏与你同在;清澈似水,纯真如玉,惟有深深的牵挂和关爱。魔扣源码论坛做你最好的朋友,无论过去、现在和将来!

该用户从未签到

2

主题

286

回帖

574

积分

高级魔扣

Rank: 4

魔扣币
286
贡献
286
威望
0
发表于 2017-5-30 08:14:54 | 显示全部楼层
激动人心,无法言表!再次感谢魔扣帮我找到此极品源码!

该用户从未签到

1

主题

281

回帖

563

积分

高级魔扣

Rank: 4

魔扣币
281
贡献
281
威望
0
发表于 2017-10-11 23:33:48 来自手机 | 显示全部楼层
当你孤独时,风儿就是我的歌声,愿它能使你得到片刻的安慰;当你骄傲时,雨点就是我的警钟,魔扣源码论坛愿它能使你获得永恒的谦逊。

该用户从未签到

1

主题

246

回帖

493

积分

中级魔扣

Rank: 3Rank: 3

魔扣币
246
贡献
246
威望
0
发表于 2018-4-1 23:34:40 | 显示全部楼层
高手云集 果断围观

该用户从未签到

1

主题

237

回帖

475

积分

中级魔扣

Rank: 3Rank: 3

魔扣币
237
贡献
237
威望
0
发表于 2018-9-28 18:19:32 | 显示全部楼层
用最美好的心情想念你,魔扣源码论坛用最温暖的笑脸惦挂你,用最宽容的心胸热爱你,用最专注的眼神凝望你,用最忠诚的心灵祝福你。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 联系我们
  • 新浪微博 :
  • 在线客服 :魔扣科技 
  • 源码QQ群 :魔扣源码论坛官方总群
  • 联系邮箱 :charlin#morko.net
  • 微信扫一扫
快速回复 返回顶部 返回列表