如何進(jìn)行g(shù)unicornArbiter源碼解析

小編今天帶大家了解如何進(jìn)行g(shù)unicorn Arbiter 源碼解析,文中知識(shí)點(diǎn)介紹的非常詳細(xì)。覺得有幫助的朋友可以跟著小編一起瀏覽文章的內(nèi)容,希望能夠幫助更多想解決這個(gè)問題的朋友找到問題的答案,下面跟著小編一起深入學(xué)習(xí)“如何進(jìn)行g(shù)unicorn Arbiter 源碼解析”的知識(shí)吧。

成都一家集口碑和實(shí)力的網(wǎng)站建設(shè)服務(wù)商,擁有專業(yè)的企業(yè)建站團(tuán)隊(duì)和靠譜的建站技術(shù),10多年企業(yè)及個(gè)人網(wǎng)站建設(shè)經(jīng)驗(yàn) ,為成都上千客戶提供網(wǎng)頁設(shè)計(jì)制作,網(wǎng)站開發(fā),企業(yè)網(wǎng)站制作建設(shè)等服務(wù),包括成都營銷型網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),同時(shí)也為不同行業(yè)的客戶提供成都做網(wǎng)站、成都網(wǎng)站建設(shè)的服務(wù),包括成都電商型網(wǎng)站制作建設(shè),裝修行業(yè)網(wǎng)站制作建設(shè),傳統(tǒng)機(jī)械行業(yè)網(wǎng)站建設(shè),傳統(tǒng)農(nóng)業(yè)行業(yè)網(wǎng)站制作建設(shè)。在成都做網(wǎng)站,選網(wǎng)站制作建設(shè)服務(wù)商就選創(chuàng)新互聯(lián)建站。

如前文所述,Arbiter是gunicorn master進(jìn)程的核心。Arbiter主要負(fù)責(zé)管理worker進(jìn)程,包括啟動(dòng)、監(jiān)控、殺掉Worker進(jìn)程;同時(shí),Arbiter在某些信號(hào)發(fā)生的時(shí)候還可以熱更新(reload)App應(yīng)用,或者在線升級(jí)gunicorn。Arbiter的核心代碼在一個(gè)文件里面,代碼量也不大,源碼在此:https://github.com/benoitc/gunicorn。

Arbiter主要有以下方法:

setup:

    處理配置項(xiàng),最重要的是worker數(shù)量和worker工作模型

init_signal

    注冊(cè)信號(hào)處理函數(shù)

handle_xxx:

    各個(gè)信號(hào)具體的處理函數(shù)

kill_worker,kill_workers:

    向worker進(jìn)程發(fā)信號(hào)

spawn_worker, spawn_workers:

    fork出新的worker進(jìn)程

murder_workers:

    殺掉一段時(shí)間內(nèi)未響應(yīng)的worker進(jìn)程

manage_workers:

    根據(jù)配置文件的worker數(shù)量,以及當(dāng)前active的worker數(shù)量,決定是要fork還是kill worker進(jìn)程

reexec

    接收到信號(hào)SIGUSR2調(diào)用,在線升級(jí)gunicorn

reload:

    接收到信號(hào)SIGHUP調(diào)用,會(huì)根據(jù)新的配置新啟動(dòng)worker進(jìn)程,并殺掉之前的worker進(jìn)程

sleep

    在沒有信號(hào)處理的時(shí)候,利用select的timeout進(jìn)行sleep,可被喚醒

wakeup

    通過向管道寫消息,喚醒進(jìn)程

run

    主循環(huán)

Arbiter真正被其他代碼(Application)調(diào)用的函數(shù)只有__init__和run方法,在一句代碼里:

    Arbiter(self).run()

上面代碼中的self即為Application實(shí)例,其中__init__調(diào)用setup進(jìn)行配置項(xiàng)設(shè)置。下面是run方法偽代碼

def run()
    self.init_signal()
    self.LISTENERS = create_sockets(self.cfg, self.log)
    self.manage_workers()    while True:        if no signal in SIG_QUEUE
            self.sleep()        else:
            handle_signal()

 關(guān)于fork子進(jìn)程

fork子進(jìn)程的代碼在 spawn_worker, 源碼如下:

如何進(jìn)行g(shù)unicorn Arbiter 源碼解析 Arbiter.spawn_worker

主要流程:

    (1)加載worker_class并實(shí)例化(默認(rèn)為同步模型 SyncWorker)

    (2)父進(jìn)程(master進(jìn)程)fork之后return,之后的邏輯都在子進(jìn)程中運(yùn)行

    (3)調(diào)用worker.init_process 進(jìn)入循環(huán),新航道雅思培訓(xùn)的所有工作都在這個(gè)循環(huán)中

    (4)循環(huán)結(jié)束之后,調(diào)用sys.exit(0)

    (5)最后,在finally中,記錄worker進(jìn)程的退出

    

    下面是我自己寫的一點(diǎn)代碼,把主要的fork流程簡(jiǎn)化了一下

 1 # prefork.py 2 import sys 3 import socket 4 import select 5 import os 6 import time 7   8 def do_sub_process(): 9     pid = os.fork()10     if pid < 0:11         print 'fork error'12         sys.exit(-1)13     elif pid > 0:14         print 'fork sub process %d'  % pid15         return16  17     # must be child process18     time.sleep(1)19     print 'sub process will exit', os.getpid(), os.getppid()20     sys.exit(0)21  22 def main():23     sub_num = 224     for i in range(sub_num):25         do_sub_process()26     time.sleep(10)27     print 'main process will exit', os.getpid()28  29 if __name__ == '__main__':30     main()

在測(cè)試環(huán)境下輸出:

fork sub process 9601

fork sub process 9602

sub process will exit 9601 9600

sub process will exit 9602 9600

main process will exit 9600

需要注意的是第20行調(diào)用了sys.exit, 保證子進(jìn)程的結(jié)束,否則會(huì)繼續(xù)main函數(shù)中for循環(huán),以及之后的邏輯。注釋掉第19行重新運(yùn)行,看輸出就明白了。

關(guān)于kill子進(jìn)程

master進(jìn)程要kill worker進(jìn)程就很簡(jiǎn)單了,直接發(fā)信號(hào),源碼如下:

 1     def kill_worker(self, pid, sig): 2         """\ 3         Kill a worker 4  5         :attr pid: int, worker pid 6         :attr sig: `signal.SIG*` value 7          """ 8         try: 9             os.kill(pid, sig)10         except OSError as e:11             if e.errno == errno.ESRCH:12                 try:13                     worker = self.WORKERS.pop(pid)14                     worker.tmp.close()15                     self.cfg.worker_exit(self, worker)16                     return17                 except (KeyError, OSError):18                     return19             raise

關(guān)于sleep與wakeup

我們?cè)賮砜纯碅rbiter的sleep和wakeup。Arbiter在沒有信號(hào)需要處理的時(shí)候會(huì)"sleep",當(dāng)然,不是真正調(diào)用time.sleep,否則信號(hào)來了也不能第一時(shí)間處理。這里得實(shí)現(xiàn)比較巧妙,利用了管道和select的timeout??创a就知道了

        def sleep(self):        """\
        Sleep until PIPE is readable or we timeout.
        A readable PIPE means a signal occurred.        """
            ready = select.select([self.PIPE[0]], [], [], 1.0) # self.PIPE = os.pipe()
            if not ready[0]: 
                return
            while os.read(self.PIPE[0], 1):                pass

代碼里面的注釋寫得非常清楚,要么PIPE可讀立即返回,要么等待超時(shí)。管道可讀是因?yàn)橛行盘?hào)發(fā)生。這里看看pipe函數(shù)

  •   os.pipe()

  • Create a pipe. Return a pair of file descriptors (r,w) usable for reading and writing, respectively.

那我們看一下什么時(shí)候管道可讀:肯定是往管道寫入的東西,這就是wakeup函數(shù)的功能

        def wakeup(self):            """
            Wake up the arbiter by writing to the PIPE            """
            os.write(self.PIPE[1], b'.')

最后附上Arbiter的信號(hào)處理

退出,INT:快速關(guān)閉

TERM: 優(yōu)雅關(guān)機(jī)。等待工作人員完成其當(dāng)前請(qǐng)求,直到超時(shí)。

HUP:重新加載配置,用新配置啟動(dòng)新的工作進(jìn)程,并優(yōu)雅地關(guān)閉舊的工作進(jìn)程。如果應(yīng)用程序未預(yù)加載(使用--preload選項(xiàng)),Gunicorn也將加載新版本。

TTIN:將進(jìn)程數(shù)增加一個(gè)

TTOU:將進(jìn)程數(shù)減少一個(gè)

USR1:重新打開日志文件

USR2:在飛行中升級(jí)Gunicorn。應(yīng)使用單獨(dú)的術(shù)語信號(hào)終止舊進(jìn)程。此信號(hào)也可用于使用預(yù)加載應(yīng)用程序的新版本。

絞盤:當(dāng)Gunicorn被守護(hù)時(shí),優(yōu)雅地關(guān)閉工作進(jìn)程。

感謝大家的閱讀,以上就是“如何進(jìn)行g(shù)unicorn Arbiter 源碼解析”的全部?jī)?nèi)容了,學(xué)會(huì)的朋友趕緊操作起來吧。相信創(chuàng)新互聯(lián)小編一定會(huì)給大家?guī)砀鼉?yōu)質(zhì)的文章。謝謝大家對(duì)創(chuàng)新互聯(lián)網(wǎng)站的支持!

名稱欄目:如何進(jìn)行g(shù)unicornArbiter源碼解析
轉(zhuǎn)載來源:http://muchs.cn/article36/ihsipg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、ChatGPT、外貿(mào)網(wǎng)站建設(shè)、定制開發(fā)、企業(yè)建站、網(wǎng)站導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)