本文地址:http://www.cnblogs.com/hhh5460/p/7397006.html
說明
以前的那個例子的思路是后端監控數據存入數據庫;前端ajax定時查詢數據庫。
這幾天在看websocket。前端有一個js庫:socket.io.js,后端python也有很多庫實現了websocket,flask就有一個好用的擴展:flask-socketio。
在參考了這里之后,將前面那個例子改寫成后端后台線程一旦產生數據,即刻推送至前端。
好處是不需要前端ajax定時查詢,節省服務器資源。
項目一共兩個文件:
- app.py
- templates/index.htmll
app.py
路由及后台線程
'''
服務器cpu監控程序
思路:后端后台線程一旦產生數據,即刻推送至前端。
好處:不需要前端ajax定時查詢,節省服務器資源。
作者:hhh5460
時間:2017.8.19
'''
import psutil
import time
from threading import Lock
from flask import Flask, render_template, session, request
from flask_socketio import SocketIO, emit
# Set this variable to "threading", "eventlet" or "gevent" to test the
# different async modes, or leave it set to None for the application to choose
# the best option based on installed packages.
async_mode = None
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, async_mode=async_mode)
thread = None
thread_lock = Lock()
# 后台線程 產生數據,即刻推送至前端
def background_thread():
"""Example of how to send server generated events to clients."""
count = 0
while True:
socketio.sleep(5)
count += 1
t = time.strftime('%M:%S', time.localtime()) # 獲取系統時間(只取分:秒)
cpus = psutil.cpu_percent(interval=None, percpu=True) # 獲取系統cpu使用率 non-blocking
socketio.emit('server_response',
{'data': [t, *cpus], 'count': count},
namespace='/test') # 注意:這里不需要客戶端連接的上下文,默認 broadcast = True !!!!!!!
@app.route('/')
def index():
return render_template('index.html', async_mode=socketio.async_mode)
# 與前端建立 socket 連接后,啟動后台線程
@socketio.on('connect', namespace='/test')
def test_connect():
global thread
with thread_lock:
if thread is None:
thread = socketio.start_background_task(target=background_thread)
if __name__ == '__main__':
socketio.run(app, debug=True)
index.html
頁面文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ECharts3 Ajax</title>
<script type="text/javascript" src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdn.bootcss.com/socket.io/1.5.1/socket.io.min.js"></script>
<!-- ECharts 3 引入 -->
<script src="http://echarts.baidu.com/dist/echarts.min.js"></script>
</head>
<body>
<!--為ECharts准備一個具備大小(寬高)的Dom-->
<div id="main" style="height:500px;border:1px solid #ccc;padding:10px;"></div>
<script type="text/javascript">
// 作者:hhh5460
// 時間:2017.8.19
//--- 折柱 ---
var myChart = echarts.init(document.getElementById('main'));
myChart.setOption({
title: {
text: '服務器系統監控'
},
tooltip: {},
legend: {
data:['cpu1','cpu2','cpu3','cpu4']
},
xAxis: {
data: []
},
yAxis: {},
series: [{
name: 'cpu1',
type: 'line',
data: []
},{
name: 'cpu2',
type: 'line',
data: []
},{
name: 'cpu3',
type: 'line',
data: []
},{
name: 'cpu4',
type: 'line',
data: []
}]
});
// 本人筆記本有四個cpu,讀者朋友請根據自己的情況,相應修改!!
// 五個全局變量:time、cpu1、cpu2、cpu3、cpu4
var time = ["","","","","","","","","",""],
cpu1 = [0,0,0,0,0,0,0,0,0,0],
cpu2 = [0,0,0,0,0,0,0,0,0,0],
cpu3 = [0,0,0,0,0,0,0,0,0,0],
cpu4 = [0,0,0,0,0,0,0,0,0,0]
//准備好統一的 callback 函數
var update_mychart = function (res) { //res是json格式的response對象
// 隱藏加載動畫
myChart.hideLoading();
// 准備數據
time.push(res.data[0]);
cpu1.push(parseFloat(res.data[1]));
cpu2.push(parseFloat(res.data[2]));
cpu3.push(parseFloat(res.data[3]));
cpu4.push(parseFloat(res.data[4]));
if (time.length >= 10){
time.shift();
cpu1.shift();
cpu2.shift();
cpu3.shift();
cpu4.shift();
}
// 填入數據
myChart.setOption({
xAxis: {
data: time
},
series: [{
name: 'cpu1', // 根據名字對應到相應的系列
data: cpu1
},{
name: 'cpu2',
data: cpu2
},{
name: 'cpu3',
data: cpu3
},{
name: 'cpu4',
data: cpu4
}]
});
};
// 首次顯示加載動畫
myChart.showLoading();
// 建立socket連接,等待服務器“推送”數據,用回調函數更新圖表
$(document).ready(function() {
namespace = '/test';
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);
socket.on('server_response', function(res) {
update_mychart(res);
});
});
</script>
</body>
</html>