supervisor(二)event

supervisor的event機(jī)制其實,就是一個監(jiān)控/通知的框架。拋開這個機(jī)制實現(xiàn)的過程來說的話蛉加,event其實就是一串?dāng)?shù)據(jù)同衣,這串?dāng)?shù)據(jù)里面有head和body兩部分竟块。咱們先弄清楚event數(shù)據(jù)結(jié)構(gòu),咱們才能做后續(xù)的處理耐齐。先看看header長啥樣的吧

ver:3.0 server:supervisor serial:21 pool:listener poolserial:10 eventname:PROCESS_COMMUNICATION_STDOUT len:54

來說說上面的這個header每一項浪秘,都是什么?

  • ver:表示event協(xié)議的版本埠况,目前是3.0

  • server:表示supervisor的標(biāo)識符耸携,也就是咱們上一篇中[supervisord]塊中的identifier選項中的東西 默認(rèn)為supervisor

  • serial:這個東西是每個event的序列號,supervisord在運行過程中辕翰,發(fā)送的第一個event的序列號就是1 接下來的event依次類推

  • pool:這個是你的listener的pool的名字违帆,一般你的listener只啟動一個進(jìn)程的的話,其實也就沒有pool的概念了金蜀。名字就是[eventlistener:theeventlistenername]這個東西

  • poolserial:上面的serial是supervisord給每個event的編號刷后。 而poolserial則是eventpool給發(fā)送到我這個pool過來的event編的號

  • eventname:這個是event的類型名稱,這個后面說渊抄。

  • len:這個長度尝胆,表示的是header后面的body部分的長度。header之后护桦,我們會取len長度的內(nèi)容作為body含衔。

    好,說完了header,咱們就該說說body部分的數(shù)據(jù)結(jié)構(gòu)了二庵。body的數(shù)據(jù)結(jié)構(gòu)贪染,其實是和event的具體類型相關(guān)的,不同的event的類型催享,header的結(jié)構(gòu)都一樣杭隙,但是body的結(jié)構(gòu)大多就不一樣了。

關(guān)于event類型因妙,咱們就不展開說了痰憎,因為太多了,具體大伙可以去參閱一下官網(wǎng)攀涵。其實搞會一個铣耘,其他也都一個樣。

咱們這里說說待會一個要用到的類型就OK了以故,啥類型呢蜗细?

是PROCESS_STATE_EXITED
看著這名字,大伙差不多也就知道它是干什么的了怒详。PROCESS_STATE_EXITED其實就是炉媒,當(dāng)supervisord管理的子進(jìn)程退出的時候踪区,supervisord就會產(chǎn)生PROCESS_STATE_EXITED這么個event。
來看看PROCESS_STATE_EXITED長啥樣吧橱野,header咱們前面說過了,都一樣善玫。來看看body部分

processname:cat groupname:cat from_state:RUNNING expected:0 pid:2766

來說說具體含義

  • processname:就是進(jìn)程名字水援,這里名字不是我們實際進(jìn)程的名字,而是咱們[program:x]配置成的名字
  • groupname:組名茅郎,這個一個樣
  • from_state:這個是蜗元,我們的進(jìn)程退出前的狀態(tài)是什么狀態(tài)
  • expected:這個咱們前面也講過,默認(rèn)情況下exitcodes是0和2系冗,也就是說0和2是expected奕扣。其它的退出碼,也就是unexpected了
  • pid:這個大伙想必都知道掌敬。
    OK惯豆,說到了這里,我們知道了event的產(chǎn)生奔害,然后給我們的listener這么一種結(jié)構(gòu)的數(shù)據(jù)楷兽。

現(xiàn)在我們有數(shù)據(jù)了,就看咱們怎么去處理這些數(shù)據(jù)了华临,這個過程就仁者見仁芯杀,智者見智了。我們可以利用接收的數(shù)據(jù)雅潭,加工后揭厚,進(jìn)行報警,等等操作扶供。
處理數(shù)據(jù)之前筛圆,咱們還得要來了解一下,listener和supervisord之間的通信過程
在這里我們首先要搞清楚椿浓,event的發(fā)起方和接收方顽染。
event的發(fā)起方是supervisord進(jìn)程,接收方是一個叫l(wèi)istener的東西轰绵,listener怎么配置粉寞,上一篇參數(shù)詳解里面已經(jīng)寫的很清楚了,大伙可以去參考下左腔,這里就不贅述了唧垦。其實listener和program一樣,都是supervisord的子進(jìn)程液样。兩者的在配置上振亮,很多選項也都一樣巧还。
其實,event還有另外一個過程坊秸,我們的program也就是我們要管理的進(jìn)程麸祷,也可以發(fā)送event,進(jìn)而和supervisord主動通信褒搔。不過program程序一般都是程序員們搞阶牍,咱們搞運維的就不管他們的事情了
OK,看看event協(xié)議星瘾。

協(xié)議其實很簡單走孽。

當(dāng)supervisord啟動的時候,如果我們的listener配置為autostart=true的話琳状,listener就會作為supervisor的子進(jìn)程被啟動磕瓷。
listener被啟動之后,會向自己的stdout寫一個"READY"的消息,此時父進(jìn)程也就是supervisord讀取到這條消息后念逞,會認(rèn)為listener處于就緒狀態(tài)困食。
listener處于就緒狀態(tài)后,當(dāng)supervisord產(chǎn)生的event在listener的配置的可接受的events中時翎承,supervisord就會把該event發(fā)送給該listener陷舅。
listener接收到event后,我們就可以根據(jù)event的head审洞,body里面的數(shù)據(jù)莱睁,做一些列的處理了。我們根據(jù)event的內(nèi)容芒澜,判斷仰剿,提取,報警等等操作痴晦。
該干的活都干完之后南吮,listener需要向自己的stdout寫一個消息"RESULT\nOK",supervisord接受到這條消息后誊酌。就知道listener處理event完畢了部凑。

好,來看看例子吧

#!/usr/bin/env python
#coding:utf-8
 
import sys
import os
import subprocess
#childutils這個模塊是supervisor的一個模型碧浊,可以方便我們處理event消息涂邀。。箱锐。當(dāng)然我們也可以自己按照協(xié)議比勉,用任何語言來寫listener,只不過用childutils更加簡便罷了
from supervisor import childutils
from optparse import OptionParser
import socket
import fcntl
import struct
 
__doc__ = "\033[32m%s,捕獲PROCESS_STATE_EXITED事件類型,當(dāng)異常退出時觸發(fā)報警\033[0m" % sys.argv[0]
 
def write_stdout(s):
    sys.stdout.write(s)
    sys.stdout.flush()
#定義異常,沒啥大用其實
class CallError(Exception):
    def __init__(self,value):
        self.value = value
    def __str__(self):
        return repr(self.value)
#定義處理event的類
class ProcessesMonitor():
    def __init__(self):
        self.stdin = sys.stdin
        self.stdout = sys.stdout
 
    def runforever(self):
        #定義一個無限循環(huán)浩聋,可以循環(huán)處理event观蜗,當(dāng)然也可以不用循環(huán),把listener的autorestart#配置為true衣洁,處理完一次event就讓該listener退出墓捻,然后supervisord重啟該listener,這樣listen#er就可以處理新的event了
        while 1:
            #下面這個東西坊夫,是向stdout發(fā)送"READY"砖第,然后就阻塞在這里,一直等到有event發(fā)過來
            #headers,payload分別是接收到的header和body的內(nèi)容
            headers, payload = childutils.listener.wait(self.stdin, self.stdout)
            #判斷event是否是咱們需要的践樱,不是的話厂画,向stdout寫入"RESULT\NOK"凸丸,并跳過當(dāng)前
            #循環(huán)的剩余部分
            if not headers['eventname'] == 'PROCESS_STATE_EXITED':
                childutils.listener.ok(self.stdout)
                continue
 
            pheaders,pdata = childutils.eventdata(payload+'\n')
            #判讀event是否是expected是否是expected的拷邢,expected的話為1,否則為0
            #這里的判斷是過濾掉expected的event
            if int(pheaders['expected']):
                childutils.listener.ok(self.stdout)
                continue
 
            ip = self.get_ip('eth0')
            #構(gòu)造報警信息結(jié)構(gòu)
            msg = "[Host:%s][Process:%s][pid:%s][exited unexpectedly fromstate:%s]" % (ip,pheaders['processname'],pheaders['pid'],pheaders['from_state'])
            #調(diào)用報警接口屎慢,這個接口是我們公司自己開發(fā)的瞭稼,大伙不能用的,要換成自己的接口
            subprocess.call("/usr/local/bin/alert.py -m '%s'" % msg,shell=True)
            #stdout寫入"RESULT\nOK"腻惠,并進(jìn)入下一次循環(huán)
            childutils.listener.ok(self.stdout)
 
 
    '''def check_user(self):
        userName = os.environ['USER']
        if userName != 'root':
            try:
                raise MyError('must be run by root!')
            except MyError as e:
                write_stderr( "Error occurred,value:%s\n" % e.value)
                sys.exit(255)'''
 
    def get_ip(self,ifname):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        inet = fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15]))
        ret = socket.inet_ntoa(inet[20:24])
        return ret
 
 
def main():
    parser = OptionParser()
    if len(sys.argv) == 2:
        if sys.argv[1] == '-h' or sys.argv[1] == '--help':
            print __doc__
            sys.exit(0)
    #(options, args) = parser.parse_args()
    #下面這個环肘,表示只有supervisord才能調(diào)用該listener,否則退出
    if not 'SUPERVISOR_SERVER_URL' in os.environ:
        try:
            raise CallError("%s must be run as a supervisor event" % sys.argv[0])
        except CallError as e:
            write_stderr("Error occurred,value: %s\n" % e.value)
 
        return
 
    prog = ProcessesMonitor()
    prog.runforever()
 
if __name__ == '__main__':
    main()

差不多就這些了集灌,其他常用的event類型悔雹,已經(jīng)listener的三種狀態(tài),已經(jīng)怎么轉(zhuǎn)換的欣喧。大伙可以去官網(wǎng)上看看

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腌零,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子唆阿,更是在濱河造成了極大的恐慌益涧,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驯鳖,死亡現(xiàn)場離奇詭異闲询,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)浅辙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門扭弧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人记舆,你說我怎么就攤上這事寄狼。” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵泊愧,是天一觀的道長伊磺。 經(jīng)常有香客問我,道長删咱,這世上最難降的妖魔是什么屑埋? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮痰滋,結(jié)果婚禮上摘能,老公的妹妹穿的比我還像新娘。我一直安慰自己敲街,他們只是感情好团搞,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著多艇,像睡著了一般逻恐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上峻黍,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天复隆,我揣著相機(jī)與錄音,去河邊找鬼姆涩。 笑死挽拂,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的骨饿。 我是一名探鬼主播亏栈,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宏赘!你這毒婦竟也來了绒北?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤置鼻,失蹤者是張志新(化名)和其女友劉穎镇饮,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箕母,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡储藐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嘶是。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钙勃。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖聂喇,靈堂內(nèi)的尸體忽然破棺而出辖源,到底是詐尸還是另有隱情蔚携,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布克饶,位于F島的核電站酝蜒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏矾湃。R本人自食惡果不足惜亡脑,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望邀跃。 院中可真熱鬧霉咨,春花似錦、人聲如沸拍屑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽僵驰。三九已至喷斋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間矢渊,已是汗流浹背继准。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工枉证, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留矮男,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓室谚,卻偏偏與公主長得像毡鉴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子秒赤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理猪瞬,服務(wù)發(fā)現(xiàn),斷路器入篮,智...
    卡卡羅2017閱讀 134,701評論 18 139
  • supervisor這東西陈瘦,其實就是用來管理進(jìn)程的。咱們?yōu)槭裁匆胹upervisor呢潮售?因為痊项,相對于我們linu...
    逗比punk閱讀 5,060評論 1 14
  • supervisor 是由python語言編寫、基于linux操作系統(tǒng)的一款服務(wù)器管理工具酥诽,用以監(jiān)控服務(wù)器的運行鞍泉,...
    每次哭都笑著奔跑閱讀 6,300評論 6 14
  • 前言 系列文章 Android Architecture Component之Lifecycle-Aware Co...
    Jason騎蝸牛看世界閱讀 3,507評論 3 20
  • 很久沒有回家肮帐, 這次回家咖驮, 拜訪了姑姑。 聽姑姑念叨自己的兒子,似乎成了心病托修。姑姑的大兒子去年在外打工忘巧,一年沒有...
    sunshineinourhe閱讀 247評論 0 0