基於python的Linux系統指定進程性能監控

        監控Linux服務器的工具、組件和程序網上有很多,但是一臺服務器上會有很多進程同時運行,特別是做性能測試的時候,可能一臺服務器上部署多個服務,如果只監控整個服務器的CPU和內存,當某個服務出現性能問題時,並不能有效準確的定位出(當然通過其他工具也可以實現),因此,很有必要只監控指定的進程。需求明確了,於是動手擼了一個性能監控腳本。

一、整體思路

1、爲了方便的啓動監控和停止監控,在想查看監控結果的時候隨時查看監控結果,用flask開啓了一個服務,通過發送get請求可以隨時啓停監控和查看監控結果。
2、針對控制是否監控cpu、內存、IO,開啓多線程監控。
3、爲了減少對其他組件的依賴,將監控結果寫到日誌中。
4、爲了方便查看監控結果,直接將結果以html方式返回。
在這裏插入圖片描述

二、配置文件

config.py

IP = '127.0.0.1'
PORT = '5555'
LEVEL = 'INFO'      # log level
BACKUP_COUNT = 9    # log backup counter
LOG_PATH = 'logs'   # log path
INTERVAL = 1  # interval, run command interval.
SLEEPTIME = 3   # interval, when stopping monitor, polling to start monitor when satisfying condition.
ERROR_TIMES = 5     # times, number of running command. When equal, automatically stopped monitor.
IS_JVM_ALERT = True     # Whether to alert when the frequency of Full GC is too high.
IS_MONITOR_SYSTEM = True    # Whether to monitor system's CPU and Memory.
IS_MEM_ALERT = True     # Whether to alert when memory is too low. Alert by sending email.
MIN_MEM = 2             # Minxium memory, uint: G
# 0: don't clear cache, 1: clear page caches, 2: clear dentries and inodes caches, 3: include 1 and 2;
# echo 1 >/proc/sys/vm/drop_caches
ECHO = 0
SMTP_SERVER = 'smtp.sina.com'       # SMTP server
SENDER_NAME = '張三'          # sender name
SENDER_EMAIL = '[email protected]'        # sender's email
PASSWORD = 'UjBWYVJFZE9RbFpIV1QwOVBUMDlQUT09'       # email password, base64 encode.
RECEIVER_NAME = 'baidu_all'     # receiver name
RECEIVER_EMAIL = ['[email protected]', '[email protected]']    # receiver's email
DISK = 'device1'   # Which disk your application runs
START_TIME = 'startTime.txt'    # Store the time of start monitoring.
FGC_TIMES = 'FullGC.txt'        # Store the time of every FullGC time.

# html
HTML = '<html><body>{}</body><html>'
ERROR = '<p style="color:red">{}</p>'
HEADER = '<div id="header"><h2 align="center">Performance Monitor (pid={})</h2></div>'
ANALYSIS = '<div id="container" style="width:730px; margin:0 auto">{}</div>'

IP和PORT:開啓服務的服務器IP和端口,必須和所監控的服務在同一臺服務器上;
BACKUP_COUNT:默認爲9,即只保留最近9天監控結果;
INTERVAL:兩次監控的時間間隔,默認爲1s,主要用於cpu和內存監控,當同時監控多個端口或進程時,請將該值設小一點;
ERROR_TIMES:命令執行失敗次數,當大於該次數時,則會自動停止監控;主要用於監控指定的進程,如果進程被殺掉,則必須自動停止監控,且必須手動觸發再次開始監控;如果監控指定的端口,當端口的進程被殺掉後,也會停止監控,如果端口被重新啓動,則自動開始監控;
IS_JVM_ALERT:僅針對java應用,如果頻繁FullGC,則郵件提醒;一般性能測試,FullGC的頻率不得小於3600秒;
IS_MONITOR_SYSTEM :是否監控系統總CPU使用率和剩餘內存;
IS_MEM_ALERT:當系統剩餘內存過低時,是否郵件提醒;
MIN_MEM:允許系統最小剩餘內存,單位爲G;
ECHO:當系統剩餘內存過低時,是否釋放緩存;0爲不釋放,1爲釋放頁面緩存,2爲釋放dentries和inodes緩存,3爲釋放1和2;
DISK:磁盤號,如果監控IO,需要輸入磁盤號,通過df -h 文件名查看當前文件掛在哪個磁盤下;
START_TIME:記錄每次手動觸發開始監控的時間;
FGC_TIMES:記錄每次FullGC的時間,用於排查問題;

三、接口和服務

server.py

server = Flask(__name__)
permon = PerMon()
# 開啓多線程
t = [threading.Thread(target=permon.write_cpu_mem, args=()),
     threading.Thread(target=permon.write_io, args=())]
for i in range(len(t)):
    t[i].start()

# 開始監控
# http://127.0.0.1:5555/runMonitor?isRun=1&type=pid&num=23121&totalTime=3600
@server.route('/runMonitor', methods=['get'])
def runMonitor():......

# 畫監控結果圖
# http://127.0.0.1:5555/plotMonitor?type=pid&num=23121
@server.route('/plotMonitor', methods=['get'])
def plotMonitor():.......

server.run(port=cfg.PORT, debug=True, host=cfg.IP)  # 開啓服務

通過在瀏覽器地址欄輸入對應的url,即可啓停監控和查看監控結果
url傳參:
1、開始監控
http://127.0.0.1:5555/runMonitor?isRun=1&type=pid&num=23121&totalTime=3600
isRun:1爲開始監控,0爲停止監控;
type和num:type=pid時,表明num爲進程號,type=port,表明num爲端口號;可以同時監控多個端口或進程,多個端口或進程用英文逗號隔開;
totalTime:爲監控總時間,單位爲秒;如果不傳入totalTime,則默認一直監控;

2、查看監控結果
http://127.0.0.1:5555/plotMonitor?type=port&num=23121&system=1&startTime=2019-08-03 08:08:08&duration=3600
type和num:type=pid時,表明num爲進程號,type=port,表明num爲端口號;
system:表示查看系統監控結果;如果傳了type和num,不管sysytem是否傳值,都只能看到進程的監控結果;不傳type和num,只傳system,則可以查看系統監控結果;
startTime:查看監控結果開始時間;
duration:查看監控結果的時長,單位爲秒;
如果不傳startTime和duration,則默認查看最近一次開始監控以來的所有結果;如果需要查看某一段時間內的監控結果,則需要傳startTime和duration,查看監控結果的時間範圍爲從startTime開始到startTime+duration爲止。
注:如果在查看監控結果輸入的一段時間內,服務被重啓過,則進程號會有變化,此時仍輸入重啓前的進程號,則只能查看對應進程號在對應時間段內的監控結果。一般情況下,端口號不會輕易變化,建議查看監控結果時輸入端口號。

四、監控

performance_monitor.py
使用top命令監控CPU和內存,使用jstat命令監控JVM內存(僅java應用),使用iotop命令監控進程讀寫磁盤,使用iostat命令監控磁盤IO,使用netstat命令根據端口查進程,使用ps命令查看服務啓動時長。因此,服務器必須支持以上命令,如不支持,請安裝。
注:由於進程可以開啓多個線程,在查看進程的IO時,是看不到任何IO;而查看進程開啓的某個線程IO時,是可以看到IO的,但是線程是一直是在變化的;故目前暫不支持監控指定進程IO的。

五、查看監控結果

draw_performance.py
1、分別畫CPU圖、內存和JVM圖、IO圖和句柄數圖;
2、爲方便統計CPU和IO使用情況,計算百分位數;
3、爲方便統計垃圾回收信息,計算java應用的ygc、fgc,以及各自的頻率。

監控結果效果圖如下:
在這裏插入圖片描述

六、擴展函數

extern.py 有兩個功能

1、端口轉進程

try:
   result = os.popen(f'netstat -nlp|grep {port} |tr -s " "').readlines()
   res = [line.strip() for line in result if str(port) in line]
   p = res[0].split(' ')
   pp = p[3].split(':')[-1]
   if str(port) == pp:
      pid = p[-1].split('/')[0]
except Exception as err:
   logger.logger.error(err)

2、查找包含監控結果的日誌
整體思路:
        (1)根據輸入的開始時間和結束時間,查找包含這段時間的所有日誌文件;
        (2)根據查找出來的日誌文件,找出包含監控結果的所有日誌;
        (3)畫圖的時候遍歷找出的所有日誌。

補充

1、爲了方便查看最近一次開始監控的時間,會將每一次開始監控的時間寫到startTime.txt文件中;
2、爲了方便排查java應用可能出現的問題,將每一次Full GC的時間寫到FullGC.txt文件中。



項目地址:https://github.com/leeyoshinari/performance_monitor

(~~ 完 ~~)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章