守護進程與Supervisor

博客連接:http://www.cnblogs.com/zhenghongxin/p/8676565.htmlphp

消息隊列處理後臺任務帶來的問題

在系統稍微大些的時候,咱們常常會用到消息隊列(實現的方式不少種,在後續會講到),好比發郵件,將郵件消息放入隊列待執行,好比發送獎勵等。能夠說,咱們是構造一個最簡單的先進先出隊列,隊列的一個成員就是一段文本。入消息隊列lpop比較容易,但在取消息隊列rpop的時候,咱們可能遇到這樣的問題:html

咱們沒法預知消息隊列什麼時候會有數據產生,因此咱們的任務執行程序還須要具有監控消息隊列的能力,也就是一個常駐後臺的守護進程。python

而PHP在通常狀況下是沒法常駐內存的,固然有了swoole後,PHP能夠常駐內存(能夠學習:MixPHP:基於 Swoole 的常駐內存型 PHP 框架),或其餘方式來實現常駐內存(workman等),而接下來面對的問題是:web

1)當守護進程運行時,Web應用可否與後臺守護進程交互,實現開啓/殺死進程的功能以及得到進程的運行狀態?shell

2)當咱們更改配置時,守護進程可否實時讀取配置而不須要整個重啓?apache

3)守護進程若是重啓,可否進行平滑的重啓,而不會丟失正在執行的消息隊列?tomcat

4)消息隊列的如何取出與意外還原保證消息的完整性?安全

簡單的php定時任務拉起消費隊列服務器

咱們能夠寫一個php消費隊列的腳本,利用定時任務,每隔幾分鐘讀取一下消息隊列,執行成功的隊列清除,每隔五分鐘拉起任務。這樣子作的優勢:代碼簡單易理解,定時任務容易配置swoole

這樣子作的缺點:

1) 最慢狀況下,消息隊列要等5分鐘纔會被消費,在某些場景下,這是沒法忍受的。

2) 消息隊列不少的狀況下,每隔五分鐘,任務被重複拉起,要考慮多種併發,堵塞的狀況。當出了問題,如何回滾?忽然間進程異常退出,隊列沒有被消費等狀況

後臺進程與定時任務雙配合

咱們能夠寫一個php消費隊列的腳本,讓其之後臺進程的方式運行,一直在後臺默默運行。不斷地等待消息隊列的產生,爲了保證這個進程發生意外斷掉,咱們須要一個守護進程來守護這個後臺進程。

守護進程(Daemon)是運行在後臺的一種特殊進程。它獨立於控制終端而且週期性地執行某種任務或等待處理某些發生的事件。顧名思義,它的做用用來守護咱們的消息隊列消費進程,它將後臺程序變成一種服務,讓服務一直處於運行狀態。當後臺程序被kill掉,守護進程會將它從新拉起。

1)守護進程最重要的特性是後臺運行。
2)守護進程必須與其運行前的環境隔離開來。這些環境包括未關閉的文件描述符,控制終端,會話和進程組,工做目錄以及文件建立掩模等。這些環境一般是守護進程從執行它的父進程(特別是shell)中繼承下來的。
3)守護進程的啓動方式有其特殊之處。它能夠在Linux系統啓動時從啓動腳本/etc/rc.d中啓動,能夠由做業規劃進程crond啓動,還能夠由用戶終端(shell)執行。

簡單的實現來講,用定時任務cron,每五分鐘檢測一下後臺進程是否正常運行,若是正常運行,那不做處理,若是後

臺進程掛掉,那將它從新拉起。

這是簡單的用cron來作守護任務的例子,不少人也提出了讓php作守護進程的方法:

1)將文件模式的屏蔽字設置爲0;
2)fork出子進程,終止父進程(保證建立守護進程的進程不是進程組的組長);
3)調用setsid建立一個新的會話;
4)將當前工做目錄改成根目錄;
5)關閉不須要的文件描述符;
6)忽略SIGCHLD信號。

具體能夠看:

如何寫php守護進程(Daemon)http://www.jb51.net/article/77205.htm

此方法步驟繁瑣麻煩,且不易維護,並不推薦這麼作

swoole來作守護進程

有朋友的公司用的是swoole來作守護進程,這方面剛開始咱們有考慮,最後決定用更加簡單的Supervisor來作

Supervisor

Supervisor是用Python開發的一套通用的進程管理程序,能將一個普通的命令行進程變爲後臺daemon,並監控進程狀態,異常退出時能自動重啓。它是經過fork/exec的方式把這些被管理的進程看成supervisor的子進程來啓動,這樣只要在supervisor的配置文件中,把要管理的進程的可執行文件的路徑寫進去便可。也實現當子進程掛掉的時候,父進程能夠準確獲取子進程掛掉的信息的,能夠選擇是否本身啓動和報警。supervisor還提供了一個功能,能夠爲supervisord或者每一個子進程,設置一個非root的user,這個user就能夠管理它對應的進程。

安裝

Supervisor是使用python開發的一個進程管工具,安裝和使用都很是簡單。使用 pip 或者 easy_install 安裝會很是方便,自動解決依賴關係。

– sudo pip install supervisor
– sudo easy_install supervisor

supervisor安裝完成後會生成三個執行程序:supervisortd、supervisorctl、echo_supervisord_conf,分別是supervisor的守護進程服務(用於接收進程管理命令)、客戶端(用於和守護進程通訊,發送管理進程的指令)、生成初始配置文件程序。

新建個保存配置的目錄:

mkdir /etc/supervisor

用生成配置的命令生成配置查看:

echo_supervisord_conf > /etc/supervisor/supervisord.conf

能夠查看 /etc/supervisor/supervisord.conf 下的配置文件

某些配置參數說明:

[unix_http_server]
file=/tmp/supervisor.sock   ;UNIX socket 文件,supervisorctl 會使用
;chmod=0700                 ;socket文件的mode,默認是0700
;chown=nobody:nogroup       ;socket文件的owner,格式:uid:gid

;[inet_http_server]         ;HTTP服務器,提供web管理界面
;port=127.0.0.1:9001        ;Web管理後臺運行的IP和端口,若是開放到公網,須要注意安全性
;username=user              ;登陸管理後臺的用戶名
;password=123               ;登陸管理後臺的密碼

[supervisord]
logfile=/tmp/supervisord.log ;日誌文件,默認是 $CWD/supervisord.log
logfile_maxbytes=50MB        ;日誌文件大小,超出會rotate,默認 50MB,若是設成0,表示不限制大小
logfile_backups=10           ;日誌文件保留備份數量默認10,設爲0表示不備份
loglevel=info                ;日誌級別,默認info,其它: debug,warn,trace
pidfile=/tmp/supervisord.pid ;pid 文件
nodaemon=false               ;是否在前臺啓動,默認是false,即以 daemon 的方式啓動
minfds=1024                  ;能夠打開的文件描述符的最小值,默認 1024
minprocs=200                 ;能夠打開的進程數的最小值,默認 200

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ;經過UNIX socket鏈接supervisord,路徑與unix_http_server部分的file一致
;serverurl=
http://127.0.0.1:9001 ; 經過HTTP的方式鏈接supervisord

; [program:xx]是被管理的進程配置參數,xx是進程的名稱
[program:xx]
command=/opt/apache-tomcat-8.0.35/bin/catalina.sh run  ; 程序啓動命令
autostart=true       ; 在supervisord啓動的時候也自動啓動
startsecs=10         ; 啓動10秒後沒有異常退出,就表示進程正常啓動了,默認爲1秒
autorestart=true     ; 程序退出後自動重啓,可選值:[unexpected,true,false],默認爲unexpected,表示進程意外殺死後才重啓
startretries=3       ; 啓動失敗自動重試次數,默認是3
user=tomcat          ; 用哪一個用戶啓動進程,默認是root
priority=999         ; 進程啓動優先級,默認999,值小的優先啓動
redirect_stderr=true ; 把stderr重定向到stdout,默認false
stdout_logfile_maxbytes=20MB  ; stdout 日誌文件大小,默認50MB
stdout_logfile_backups = 20   ; stdout 日誌文件備份數,默認是10
; stdout 日誌文件,須要注意當指定目錄不存在時沒法正常啓動,因此須要手動建立目錄(supervisord 會自動建立日誌文件)
stdout_logfile=/opt/apache-tomcat-8.0.35/logs/catalina.out
stopasgroup=false     ;默認爲false,進程被殺死時,是否向這個進程組發送stop信號,包括子進程
killasgroup=false     ;默認爲false,向進程組發送kill信號,包括子進程

;包含其它配置文件
[include]
files = relative/directory/*.ini    ;能夠指定一個或多個以.ini結束的配置文件

更爲具體的配置,咱們能夠查看:

https://blog.csdn.net/xyang81/article/details/51555473

上面有更爲詳細的開機啓動,web管理等各項說明,在此我不列舉了

我本地的簡略配置爲:

command=php /phpstudy/www/index.php
stdout_logfile=/tmp/catalina.out
autostart=true
user=root
autorestart=true
startsecs=5
priority=1
stopasgroup=true
killasgroup=true

啓動後,能夠嘗試kill掉index.php進程,幾秒內進程都會從新被拉起

*** 值得注意的是:若是你在代碼中,刻意的去退出進程,那supervisor依舊會幫你從新拉起。

相關文章
相關標籤/搜索