1. 程式人生 > >swoole創建工作進程,執行滯後工作

swoole創建工作進程,執行滯後工作

php pid false brush class usr sta rest pac

一,創建守候進程,因為這裏不需要Server,也沒有Client,數據交換通過redis進行

<?php
namespace Kuba\Saas;
require_once __DIR__ . ‘/Core/ErrorHandle.php‘;
use \Swoole\Timer;
use \Swoole\Process;
use Kuba\Saas\Core\ErrorHandle;

final class Services {

    private $m_workers = [];
    private $m_pid = 0;
	
    public function __construct() {
        try {
            $this->m_pid = posix_getpid();
            
            echo "moolan_services start:".$this->m_pid.PHP_EOL;
            echo date("Y-m-d H:i:s").PHP_EOL;
            
            \swoole_set_process_name("moolan_services");

            $this->create_error_monitor_process($this->m_pid);

            //監控子進程的狀態,如果子進程異常退出,則重啟該子進程
            $this->process_monitor();
        }catch (\Exception $e){
            die(‘ALL ERROR: ‘.$e->getMessage());
        }        
    }
    
    private function process_monitor()
    {       
        //檢測子進程是否結束,如果結束,則重新啟動子進程 
        while(1) {
            if(count($this->m_workers)){
                //這裏會一直等待,一次接收一個子進程,所以外面必須有循環
                $ret = \swoole_process::wait();
                if ($ret) {
                    $this->process_reboot($ret);
                }
            }             
        }        
    }
    
    private function process_reboot($ret){
        try
        {
            $pid=$ret[‘pid‘];

            if(in_array($pid, $this->m_workers)){
                $method_name = $this->m_workers[$pid];
                unset($this->m_workers[$pid]);

                echo $method_name." restart:".$pid.PHP_EOL;
                echo date("Y-m-d H:i:s").PHP_EOL;                
                
                $method = new \ReflectionMethod($this, $method_name);
                $method->invoke($this, [$this->m_pid]);

                return;
            }
        }
        catch (\Exception $e)
        {
            die(‘Process_reboot error: ‘.$e->getMessage());
        }
    }    
    
    /**
     * 創建監控系統錯誤的進程
     * 
     * 該進程屬於一條一條處理的模式,因為錯誤不會太多
     */
    private function create_error_monitor_process($mpid)
    {
        try
        {
            $process = new Process(function ($worker) use ($mpid)
            {
                try
                {               
                    \swoole_set_process_name("moolan_error_handle");

                    $obj_error_handle = new ErrorHandle();
                    while (true)
                    {
                        try
                        {
                            //從消息隊列接收出錯消息,接收到一個,就啟動一個task去執行                
                            //如果接收不到出錯信息,則休息2秒時間
                            if (!$obj_error_handle->fetch_task())
                            {
                                $obj_error_handle->release_task();
                                unset($obj_error_handle);

                                usleep(2000000);

                                $obj_error_handle = new ErrorHandle();
                            }
                            else
                            {
                                //啟動任務處理接收到的出錯信息
                                $obj_error_handle->do_task();
                            }

                            //執行完一個完成的任務後,
                            //查看主進程是否已經關閉,如果已經關閉,則子進程也要關閉運行
                            if(!\swoole_process::kill($mpid,0)){
                                echo ‘moolan service gone‘.PHP_EOL;
                                echo __METHOD__.‘ process exit‘.PHP_EOL;
                                $worker->exit();
                            }
                        }
                        catch (\Exception $e)
                        {
                            echo $e->getMessage();
                        }
                    }   
                }
                catch (\Exception $e)
                {
                    die(__METHOD__.‘ process exec error: ‘.$e->getMessage());
                }
            }, false);

            $pid = $process->start();
            
            echo __METHOD__." started:".$pid.PHP_EOL;
            echo date("Y-m-d H:i:s").PHP_EOL;             
            
            $this->m_workers[$pid] = __METHOD__;
        }
        catch (\Exception $e)
        {
            die(__METHOD__.‘ Process Start error: ‘.$e->getMessage());
        }
    }

}

$server = new Services();

  二,創建值守腳本,檢測以上主進程持續運行

#! /bin/sh

proc_name="***"                    # 進程名
proc_file="***.php"
log_name="/***/moolan-monitor.log"                  # 日誌文件
pid=0

proc_num()                                             # 計算進程數
{
        num=`ps -ef | grep $proc_name | grep -v grep | wc -l`
        return $num
}

proc_id()                                               # 進程號
{
        pid=`ps -ef | grep $proc_name | grep -v grep | awk ‘{print $2}‘`
}

proc_num
number=$?
if [ $number -eq 0 ]                                    # 判斷進程是否存在
then 
        nohup /usr/local/php5/bin/php /***/$proc_file >>$log_name 2>&1 &                 # 重啟進程的命令,請相應修改
        proc_id                                               # 獲取新進程號
        echo ${pid}, `date` >>  $log_name                    # 將新進程號和重啟時間記錄
fi

  三,把值守腳本加入到定時器

crontab

利用定時任務來輪詢執行腳本

*/1 * * * * /PATH/watch_queue.sh

swoole創建工作進程,執行滯後工作