此範例來自

http://www.php.net/manual/en/function.pcntl-fork.php

通常用在需要大量呼叫SOAP API或RestfulAPI時使用

比方說我有1000張照片,我要用API取得這1000張照片的資訊,每呼叫一次api就需要1秒

1000張就約需要1000秒

如果用multi-process,一次送25個request,相當於速度提升25倍(不考慮其他因素如cpu、memory、api端的loading)

 

<?php 
declare(ticks=1); 
//A very basic job daemon that you can extend to your needs. 
class JobDaemon

    public 
maxProcesses 25
    protected 
jobsStarted 0
    protected 
currentJobs = array(); 
    protected 
signalQueue=array();   
    protected 
parentPID
   
    public function 
__construct(){ 
        echo 
"constructed \n"
        
this->parentPID getmypid(); 
        
pcntl_signal(SIGCHLD, array(this"childSignalHandler")); 
    } 
   
    
/** 
    * Run the Daemon 
    */ 
    
public function run(){ 
        echo 
"Running \n"
        for(
i=0i<10000i++){ 
            
jobID rand(0,10000000000000); 

            while(
count(this->currentJobs) >= this->maxProcesses){ 
               echo 
"Maximum children allowed, waiting...\n"
               
sleep(1); 
            } 

            
launched this->launchJob(jobID); 
        } 
       
        
//Wait for child processes to finish before exiting here 
        
while(count(this->currentJobs)){ 
            echo 
"Waiting for current jobs to finish... \n"
            
sleep(1); 
        } 
    } 
   
    
/** 
    * Launch a job from the job queue 
    */ 
    
protected function launchJob(jobID){ 
        
pid pcntl_fork(); 
        if(
pid == -1){ 
            
//Problem launching the job 
            
error_log('Could not launch new job, exiting'); 
            return 
false
        } 
        else if (
pid){ 
            
// Parent process 
            // Sometimes you can receive a signal to the childSignalHandler function before this code executes if 
            // the child script executes quickly enough! 
            // 
            
this->currentJobs[pid] = jobID
           
            
// In the event that a signal for this pid was caught before we get here, it will be in our signalQueue array 
            // So let's go ahead and process it now as if we'd just received the signal 
            
if(isset(this->signalQueue[pid])){ 
                echo 
"found pid in the signal queue, processing it now \n"
                
this->childSignalHandler(SIGCHLDpidthis->signalQueue[pid]); 
                unset(
this->signalQueue[pid]); 
            } 
        } 
        else{ 
            
//Forked child, do your deeds.... 
            
exitStatus 0//Error code if you need to or whatever 
            
echo "Doing something fun in pid ".getmypid()."\n"
            exit(
exitStatus); 
        } 
        return 
true
    } 
   
    public function 
childSignalHandler(signopid=nullstatus=null){ 
       
        
//If no pid is provided, that means we're getting the signal from the system.  Let's figure out 
        //which child process ended 
        
if(!pid){ 
            
pid pcntl_waitpid(-1statusWNOHANG); 
        } 
       
        
//Make sure we get all of the exited children 
        
while(pid 0){ 
            if(
pid && isset(this->currentJobs[pid])){ 
                
exitCode pcntl_wexitstatus(status); 
                if(
exitCode != 0){ 
                    echo 
"pid exited with status ".exitCode."\n"
                } 
                unset(
this->currentJobs[pid]); 
            } 
            else if(
pid){ 
                
//Oh no, our job has finished before this parent process could even note that it had been launched! 
                //Let's make note of it and handle it when the parent process is ready for it 
                
echo "..... Adding pid to the signal queue ..... \n"
                
this->signalQueue[pid] = status
            } 
            
pid pcntl_waitpid(-1statusWNOHANG); 
        } 
        return 
true
    } 
}

文章標籤
全站熱搜
創作者介紹
創作者 Oscar 的頭像
Oscar

小亮吉他教學&程式筆記

Oscar 發表在 痞客邦 留言(0) 人氣(4,733)