iT邦幫忙

DAY 27
3

MySQL漫談,由使用Python撰寫之MySQL工具程式出發系列 第 27

MySQL漫談,由使用Python撰寫之MySQL工具程式出發(27)

今天將探討MySQL的CPU使用量與Memory使用量.之前已經介紹了
系統的CPU使用量與Memory使用量的獲取及繪圖.但若要對某一特定
程式如MySQL或Apache等主要服務作監控,要如何作呢?
們可以利用top或是pidstat等指令來間接獲取,較為簡便.以下
將使用top指令的功能,來對Mysql Daemon的CPU使用量及Memory使用量,
獲取及儲存到RRD,再透過RRD的繪圖功能,將這兩個數據同時繪製在圖形上,
可以獲得一個直觀的概念,同樣的方法在昨天的 溫度-風扇轉速 對照圖,
也使用過.

首先是建立rrd的程式.

#!/usr/bin/env python
# ------------------------
# Python RRDTool MySQL
# MySQL CPU & Memory
# create rrd file
# -----------------------

import rrdtool

rrdtool.create(
    'mysql1.rrd', '--step', '60',
    'DS:cpu:GAUGE:120:0:U',
    'DS:mem:GAUGE:120:0:U',
    'RRA:AVERAGE:0.5:1:2880',
    'RRA:AVERAGE:0.5:30:672',
    'RRA:AVERAGE:0.5:60:744',
    'RRA:AVERAGE:0.5:720:732',
    'RRA:MAX:0.5:1:2880',
    'RRA:MAX:0.5:30:672',
    'RRA:MAX:0.5:60:744',
    'RRA:MAX:0.5:720:732',
    'RRA:MIN:0.5:1:2880',
    'RRA:MIN:0.5:30:672',
    'RRA:MIN:0.5:60:744',
    'RRA:MIN:0.5:720:732',
    'RRA:LAST:0.5:1:2880',
    'RRA:LAST:0.5:30:672',
    'RRA:LAST:0.5:60:744',
    'RRA:LAST:0.5:720:732')

再來是獲取及儲存的程式.

#!/usr/bin/env python
# --------------------
# Python RRDTool MySQL
# CPU & Memory
# update rrd file
# --------------------
import time
import subprocess
import rrdtool

def update_rrd():
    # Get pid of mysqld 
    output = subprocess.check_output('ps aux | grep mysqld', shell=True,)
    eachlines = output.splitlines()
    first = eachlines[0]
    pid = first.split()[1]
    # Using Top
    topcmd = 'top -b -n 1 -p ' + pid
    output = subprocess.check_output(topcmd, shell=True,)
    eachlines = output.splitlines()
    eachlines = eachlines[:-1]
    for line in eachlines:
        data = line.split()
        if len(data) > 0:
            if data[0] == 'Mem:':
                totalmem = int(data[1][:-1])
            if data[0] == pid:
                mysql_cpu = float(data[8])
                mysql_mem_per = float(data[9])
    #
    mem_usage = totalmem * mysql_mem_per / 100 
    rrdtool.update('mysql1.rrd', 'N:' + `mysql_cpu` + ':' + `mem_usage`)
#
if __name__ == '__main__':
     while 1:
        update_rrd()
        time.sleep(59)

注意到這裡讓程式 sleep 59秒,之前其他類似的程式都是sleep 60秒,為何這裡要
sleep 59秒? 因為我們使用指令來獲取CPU使用量,需要有間隔,top程式才能以
兩個時刻CPU計數器的差異值,換算出CPU使用量,top程式設定間隔1秒,所以後面
的sleep 只需59秒.
接著是繪圖的程式.

#!/usr/bin/env python
# ---------------------------
# Python RRDTool 
# MySQL CPU & Memory Data
# Create Image from rrd file
# ---------------------------

import rrdtool
import datetime

def mysql_graph(rrdfile, period):
    timenow = datetime.datetime.now()
    disptime = datetime.datetime.strftime(timenow, '%Y-%m-%d %H-%M-%S')
    title = 'MySQL_CPU_Memory_%s' % period
    filename = title + '.png'
    
    # -------------------
    cpu = 'DEF:cpu=%s:cpu:AVERAGE' % rrdfile
    mem = 'DEF:mem=%s:mem:AVERAGE' % rrdfile
    mem_mega = 'CDEF:mem_mega=mem,1024,/'
    mega100 = 'CDEF:mega100=mem_mega,100,/'
    # -------------------
    if period == 'yesterday':
        start = 'end-1d'
        end = '00:00'
    if period == 'today':
        start = '00:00'
        end = '23:59'
    if period == '2h':
        start = '-2h'
        end = 'now'
        
    rrdtool.graph(
        filename,
        '--start', start,
        '--end', end,
        '--title', title,
        '-a', 'PNG',
        '-W', 'Hitomitanaka for ITHelp',
        '--slope-mode',
        '--vertical-label=CPU Percent',
        '--rigid',
        '--lower-limit', '0',
        '--width', '500',
        '--height', '150',
        '--right-axis', '100:0',
        '--right-axis-label=Mega',
        '--x-grid', 'HOUR:1:HOUR:2:HOUR:2:0:%H',
        '--alt-y-grid',
        '--color', 'BACK#000000',
        '--color', 'CANVAS#000000',
        '--color', 'FONT#FFF978',
        '--font=LEGEND:7',
        '--font', 'TITLE:8:',
        '--font', 'UNIT:7:',
        '--font', 'WATERMARK:9',
        # ---------------------------------
        cpu,
        mem,
        mem_mega,
        mega100,
        #----------------------------------
        'AREA:mega100#EEEE0088:Memory Usage',
        'GPRINT:mem_mega:LAST:     Current\\: %.01lf',
        'GPRINT:mem_mega:AVERAGE:  Average\\: %.01lf',
        'GPRINT:mem_mega:MIN:  Min\\: %.01lf',
        'GPRINT:mem_mega:MAX:  Max\\: %.01lf\\n',
        'LINE2:cpu#FF32B1:CPU Utilization',
        'GPRINT:cpu:LAST:  Current\\: %.01lf',
        'GPRINT:cpu:AVERAGE:    Average\\: %.01lf',
        'GPRINT:cpu:MIN:    Min\\: %.01lf',
        'GPRINT:cpu:MAX:    Max\\: %.01lf\\n',
        'COMMENT:\t\t\t\t\tUpdate Time %s' % disptime)
#
if __name__ == '__main__':
    mysql_graph('mysql1.rrd', 'today')
    mysql_graph('mysql1.rrd', '2h')

使用簡易的壓力測試,然後繪製出壓力測試期間,CPU使用量與Memory使用量對照圖.






前面三張是壓力測試初期,可以很明顯看到記憶體用量變化不大,CPU用量隨著
壓力測試運作而有高低起伏,因為此簡易壓力測試程式,只有登入一個session,
此期間筆者也另外登入一個session,所以可以看到Memory使用量略有增加.
第4張圖,CPU使用量達到67,這時候圖形比例調整的關係,此一峰值很顯著,
但是記憶體的圖形相對就變得不明顯了.第5圖是後續的圖形,如同第4張圖
會受到峰值影響.
我們在利用RRD繪圖時,要注意此一情形,當有特別高或低的值出現時,整體都會受到
影響,所以我們可以再選擇繪圖時段,如1~3圖,以利對照,或是可以另行繪製獨立的圖形.
接著看第6張圖,是使用全天區間,這時候CPU的峰值卻回報為23 !?
為何是這樣呢?
這就要了解RRD的原理.我們一開始建立rrd的時候,有設定1分鐘的資料會存放2880筆,
相當於2天.

請看第7張圖形,在隔天採用寬度1440來繪製昨天的圖形,因為資料能夠達到每分鐘
一筆,與1440是符合的,所以沒有任何變化,也是繪製與回報CPU使用量為67.
但是第6張圖是用寬度500來繪製,當1440筆資料以500寬度來匯製,會大約採用3分鐘
區間來平均後得到估計值,故在第6張圖回報峰值為23.
RRD使用廣泛,適合使用數據的長時間觀察,會逐漸的平均,隨著時間流逝,
數值是用平均的;而且圖形的大小,也會影響其回報數據.
當我們進行測試需要較精細的數值時,需要將繪圖區間縮小,繪製後再備份.
或是採用筆者之前介紹的方法,將資料存放到MySQL Archive引擎的Table中,
再利用其他繪圖的程式,才不致受到RRD的逐漸平均的影響.
RRD使用廣泛,在許多系統均有利用,但是圖形大小與區間多為固定,
我們若能夠了解其特性,自行繪製圖形,當能對系統狀態有更深入的了解.


上一篇
MySQL漫談,由使用Python撰寫之MySQL工具程式出發(26)
下一篇
MySQL漫談,由使用Python撰寫之MySQL工具程式出發(28)
系列文
MySQL漫談,由使用Python撰寫之MySQL工具程式出發30

2 則留言

0
patrickcheng
iT邦新手 4 級 ‧ 2012-10-30 09:48:13

看了這篇,我想來寫個觀測 Android APP 資源使用的程式了。

0
ted99tw
iT邦高手 1 級 ‧ 2012-10-30 16:47:29

讚讚讚
強推!!強推!!強推!!
拍手拍手拍手

我要留言

立即登入留言