2010-01-06 3 views
4

처리해야하는 데이터의 대기열 (Amazon SQS)이 있으며 여러 프로세스 (PHP)에서 처리하려고합니다.PHP로 여러 프로세스를 생성하여 데이터를 처리합니다.

 


while(true) { 

    $array = $queue->fetchNItems(10); // get 10 items 

    if(!count($array)) 
     killProcess(); 

    foreach($array as $item) { 
     ... // process the item 
     $queue->remove($item); 
    } 

    sleep(2); 
} 

 

내가 항상 실행되도록 한 자식 프로세스가 필요하지만, 필요의 시간에 나는 (포크?) 아이 원하는 :

나는 자식 직원이 (pseduoish 코드) 같은 것을하고 싶어 큐를보다 빠르게 처리하는 데 도움이 될 수 있습니다.

내가 원한 PHP 골격을 누군가가 도와 주거나 올바른 방향으로 나를 가리킬 수 있습니까?

제가 http://php.net/manual/en/function.pcntl-fork.php을 살펴볼 필요가 있다고 생각하지만, 여러 프로세스를 관리하는 데 어떻게 이것을 사용할 수 있는지 잘 모르겠습니다.

+1

이런 종류의 것은 실제로 PHP가 의도 한 것이거나 그렇지 않습니다. 포킹 프로세스는 스레드를 생성하는 것보다 훨씬 비쌉니다. 이는 일반적으로 수행되는 방식입니다. – cletus

+1

파이썬에서 스레드로 쉽게이 작업을 수행 할 수 있습니다. 특정 이유로 PHP 만 사용할 수있는 유일한 옵션입니다. – mmattax

+0

글쎄 파이썬은 멀티 쓰레드 코드와 관련된 문제가 있습니다. 특히 CPython의 GIL이 그 중 하나입니다. Jython/IronPython에는이 문제가 없지만 컴파일해야한다고 생각합니다. – cletus

답변

2

프로세스를 포크 할 때. 당신은 그 과정의 사본을 만듭니다. 즉, 복사본 (fork)에는 원래 프로세스의 모든 내용 (파일 핸들 포함)이 포함됩니다.

부모 또는 분기 프로세스인지 어떻게 알 수 있습니까? 링크 된 페이지에서

의 예는이 꽤 명확하게

<?php 

$pid = pcntl_fork(); 
if ($pid == -1) { 
    die('could not fork'); 
} else if ($pid) { 
    // we are the parent 
    pcntl_wait($status); //Protect against Zombie children 
} else { 
    // we are the child 
} 

?> 

가 사용 (이 인스턴스의 낭비)

<?php 

$pid = pcntl_fork(); 
if ($pid == -1) { 
    die('could not fork'); 
} else if ($pid) { 
    // we are the parent 
    pcntl_wait($status); //Protect against Zombie children 
} else { 
    // we are the child 
    while(true) { 

     $array = $queue->fetchNItems(10); // get 10 items 

     if(!count($array)) { 
      exit(); 
     } 

     foreach($array as $item) { 
       ... // process the item 
       $queue->remove($item); 
     } 

     sleep(2); 
    } 
} 

?> 
이 갈래의 프로세스를 생성합니다

을 원하는이 확장을 보여줍니다 루프를 사용하여 여러 프로세스를 작성하십시오. 자식이 종료하면 자식 프로세스가 종료됩니다. 부모가 계속할 수 있도록 pcntl_wait()가 리턴됩니다. php에 대해서는 잘 모르지만 부모 프로세스가 죽거나 종료하면 자식 프로세스가 종료되지 않아도 자식 프로세스가 종료됩니다. 그러므로 pcntl_wait. 여러 자녀를 산다면 더 정교한 시스템이 필요합니다.

아마도 exec보다는 exec 함수의 범위를 살펴 봐야할까요?

경고.

forking 프로세스는 문제가 발생할 수 있으며, 데이터베이스 핸들은 자식 프로세스가 종료 될 때 닫힙니다. 또한 문제가 발생하면 많은 프로세스가있는 서버를 종료 할 수 있습니다. 놀고 테스트하고 읽는 데 많은 시간을 소비합니다.

DC는

0

나는이 오래된 스레드 알지만, 그것을 더 완전한 대답을 사용할 수 있습니다처럼 보였다. 이것은 일반적으로 PHP에서 여러 프로세스를 생성하는 방법입니다.

주의 사항 : PHP was meant to die. 의미는 몇 초 동안 실행 한 다음 종료하는 것을 의미합니다. 하지만 PHP에서의 가비지 정리는 먼 길을왔다. 조심해야한다. 예기치 않은 메모리 소비 또는 기타 이상한 현상이 있는지 프로세스를 모니터링하십시오. 당신이 그것을 설정하고 잊어 버리기 전에 잠시 동안 호크와 같은 모든 것을 보아라. 그리고 그때까지도, 때때로 프로세스를 한 번 확인하거나, 어떤 것이 어색 해지면 자동으로 알려주도록하십시오.

입력 할 때, github에도 올려 놓는 것이 좋습니다.

프로그램을 실행할 준비가되면 로그에서 tail -f를 사용하여 출력을 확인하는 것이 좋습니다.

<?php 
/* 
* date: 27-sep-2015 
* auth: robert smith 
* info: run a php daemon process 
* lic : MIT License (see LICENSE.txt for details) 
*/  
$pwd = realpath(""); 

$daemon = array(
    "log"  => $pwd."/service.log", 
    "errorLog" => $pwd."/service.error.log", 
    "pid_file" => $pwd."/", 
    "pid"  => "", 
    "stdout" => NULL, 
    "stderr" => NULL, 
    "callback" => array("myProcessA", "myProcessB") 
); 

/* 
* main (spawn new process) 
*/ 
foreach ($daemon["callback"] as $k => &$v) 
    { 
    $pid = pcntl_fork(); 

    if ($pid < 0) 
    exit("fork failed: unable to fork\n"); 

    if ($pid == 0) 
    spawnChores($daemon, $v); 
    } 

exit("fork succeeded, spawning process\n"); 
/* 
* end main 
*/ 

/* 
* functions 
*/ 
function spawnChores(&$daemon, &$callback) 
    { 
    // become own session 
    $sid = posix_setsid(); 

    if ($sid < 0) 
    exit("fork failed: unable to become a session leader\n"); 

    // set working directory as root (so files & dirs are not locked because of process) 
    chdir("/"); 

    // close open parent file descriptors system STDIN, STDOUT, STDERR 
    fclose(STDIN); 
    fclose(STDOUT); 
    fclose(STDERR); 

    // setup custom file descriptors 
    $daemon["stdout"] = fopen($daemon["log"], "ab"); 
    $daemon["stderr"] = fopen($daemon["errorLog"], "ab"); 

    // publish pid 
    $daemon["pid"] = sprintf("%d", getmypid()); 
    file_put_contents($daemon["pid_file"].$callback.".pid", $daemon["pid"]."\n"); 

    // publish start message to log 
    fprintf($daemon["stdout"], "%s daemon %s started with pid %s\n", date("Y-M-d H:i:s"), $callback, $daemon["pid"]); 

    call_user_func($callback, $daemon); 

    // publish finish message to log 
    fprintf($daemon["stdout"], "%s daemon %s terminated with pid %s\n", date("Y-M-d H:i:s"), $callback, $daemon["pid"]); 

    exit(0); 
    } 

function myProcessA(&$daemon) 
    { 
    $run_for_seconds = 30; 
    for($i=0; $i<$run_for_seconds; $i++) 
    { 
    fprintf($daemon["stdout"], "Just being a process, %s, for %d more seconds\n", __FUNCTION__, $run_for_seconds - $i); 
    sleep(1); 
    } 
    } 

function myProcessB(&$daemon) 
    { 
    $run_for_seconds = 30; 
    for($i=0; $i<$run_for_seconds; $i++) 
    { 
    fprintf($daemon["stdout"], "Just being a process, %s, for %d/%d seconds\n", __FUNCTION__, $i, $run_for_seconds); 
    sleep(1); 
    } 
    } 
?> 
관련 문제