2009-04-15 16 views
14

समस्या: मैं कई PHP-कार्यकर्ता प्रक्रियाओं को कार्यान्वित करना चाहता हूं जो एसिंक्रोनस नौकरियों के लिए एमक्यू-सर्वर कतार पर सुन रहे हैं। समस्या यह है कि बस इस प्रक्रिया को चलाने के रूप में सर्वर पर डेमन्स वास्तव में मुझे उदाहरणों (लोड, स्थिति, लॉक अप) पर नियंत्रण का कोई स्तर नहीं देता है ... शायद ps -aux डंप करने के लिए छोड़कर। इसके कारण मैं किसी प्रकार का रनटाइम वातावरण ढूंढ रहा हूं जो मुझे सिस्टम (प्रक्रिया) स्तर पर या उच्च परत (किसी प्रकार का जावा-स्टाइल एप्सर्वर) पर उदाहरणों की निगरानी और नियंत्रण करने देता हैPHP डेमॉन/कार्यकर्ता वातावरण

कोई भी संकेत दिए गए?

+0

यह भी देखें: http://symfony.com/doc/master/components/process.html –

उत्तर

12

यहां कुछ कोड है जो उपयोगी हो सकता है।

<? 
define('WANT_PROCESSORS', 5); 
define('PROCESSOR_EXECUTABLE', '/path/to/your/processor'); 
set_time_limit(0); 
$cycles = 0; 
$run = true; 
$reload = false; 
declare(ticks = 30); 

function signal_handler($signal) { 
    switch($signal) { 
    case SIGTERM : 
     global $run; 
     $run = false; 
     break; 
    case SIGHUP : 
     global $reload; 
     $reload = true; 
     break; 
    } 
} 

pcntl_signal(SIGTERM, 'signal_handler'); 
pcntl_signal(SIGHUP, 'signal_handler'); 

function spawn_processor() { 
    $pid = pcntl_fork(); 
    if($pid) { 
     global $processors; 
     $processors[] = $pid; 
    } else { 
     if(posix_setsid() == -1) 
      die("Forked process could not detach from terminal\n"); 
     fclose(stdin); 
     fclose(stdout); 
     fclose(stderr); 
     pcntl_exec(PROCESSOR_EXECUTABLE); 
     die('Failed to fork ' . PROCESSOR_EXECUTABLE . "\n"); 
    } 
} 

function spawn_processors() { 
    global $processors; 
    if($processors) 
     kill_processors(); 
    $processors = array(); 
    for($ix = 0; $ix < WANT_PROCESSORS; $ix++) 
     spawn_processor(); 
} 

function kill_processors() { 
    global $processors; 
    foreach($processors as $processor) 
     posix_kill($processor, SIGTERM); 
    foreach($processors as $processor) 
     pcntl_waitpid($processor); 
    unset($processors); 
} 

function check_processors() { 
    global $processors; 
    $valid = array(); 
    foreach($processors as $processor) { 
     pcntl_waitpid($processor, $status, WNOHANG); 
     if(posix_getsid($processor)) 
      $valid[] = $processor; 
    } 
    $processors = $valid; 
    if(count($processors) > WANT_PROCESSORS) { 
     for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--) 
      posix_kill($processors[$ix], SIGTERM); 
     for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--) 
      pcntl_waitpid($processors[$ix]); 
    } elseif(count($processors) < WANT_PROCESSORS) { 
     for($ix = count($processors); $ix < WANT_PROCESSORS; $ix++) 
      spawn_processor(); 
    } 
} 

spawn_processors(); 

while($run) { 
    $cycles++; 
    if($reload) { 
     $reload = false; 
     kill_processors(); 
     spawn_processors(); 
    } else { 
     check_processors(); 
    } 
    usleep(150000); 
} 
kill_processors(); 
pcntl_wait(); 
?> 
+0

आप इस कहाँ से मिली? ओपन सोर्स प्रोजेक्ट या अपना कोड? यहां पर वास्तव में क्या चल रहा है इसका कोई दस्तावेज़ीकरण या स्पष्टीकरण? – leek

+0

मेरा खुद का कोड। मैं इसे समझाने के इच्छुक नहीं हूं, नहीं। – chaos

+0

इसके अलावा, https://github.com/kvz/system_daemon। – HyderA

1

क्या आपको वास्तव में इसे लगातार चलने की आवश्यकता है?

यदि आप केवल अनुरोध पर नई प्रक्रिया तैयार करना चाहते हैं, तो आप इसे xinetd में एक सेवा के रूप में पंजीकृत कर सकते हैं।

+0

स्पॉन्गिंग-पहलू एक बड़ा मुद्दा नहीं है क्योंकि श्रमिकों की संख्या सिस्टम प्रदर्शन पर निर्भर करती है जो आम तौर पर स्थिर होती है। व्यक्तिगत कार्यकर्ता की स्थिति (क्रैश, जो भी हो) का निगरानी पहलू अधिक महत्वपूर्ण होगा। एक उपकरण जिसे मैंने अभी खोजा है वह डीजेबी डीमोंटोल्स – Sebastian

+0

हो सकता है यह एक विकल्प है। निगरानी के लिए आप झुंड() - एड पीआईडी ​​फाइलों का भी उपयोग कर सकते हैं। दुर्घटनाग्रस्त होने पर सभी ताले जारी किए जाते हैं। – vartec

4

ऐसा लगता है कि आपके पास पहले से ही एक एमक्यू है और * निक्स सिस्टम पर चल रहा है और केवल कर्मचारियों को प्रबंधित करने का एक तरीका चाहते हैं।

ऐसा करने का एक बहुत ही आसान तरीका जीएनयू स्क्रीन का उपयोग करना है। 10 श्रमिकों शुरू करने के लिए आप का उपयोग कर सकते हैं:

#!/bin/sh 
for x in `seq 1 10` ; do 
screen -dmS worker_$x php /path/to/script.php worker$x 
end 

यह इतने पर worker_1,2,3 नामित स्क्रीन का प्रयोग पृष्ठभूमि में 10 श्रमिकों शुरू करने और होगा।

आप स्क्रीन-आर कार्यकर्ता चलाकर स्क्रीन पर दोबारा जुड़ सकते हैं और स्क्रीन -लिस्ट का उपयोग कर चल रहे श्रमिकों को सूचीबद्ध कर सकते हैं। http://www.kuro5hin.org/story/2004/3/9/16838/14935

इसके अलावा कोशिश:

  • स्क्रीन --help
  • आदमी स्क्रीन
  • या google

    अधिक जानकारी इस गाइड मदद की हो सकती है के लिए

उत्पादन सर्वर के लिए मैं सामान्य रूप से सामान्य सिस्टम स्टार्टअप स्क्रिप्ट का उपयोग करने की अनुशंसा करता हूं, लेकिन मैं बिना किसी समस्या के स्टार्टअप स्क्रिप्ट से स्क्रीन कमांड चला रहा हूं।

0

Bellow @chaos जवाब के बारे में हमारी काम करने कार्यान्वयन है के लिए एक pcntl प्लगइन प्रकार सर्वर डेमॉन। सिग्नल को संभालने के लिए कोड हटा दिया गया था क्योंकि इस स्क्रिप्ट में आमतौर पर केवल कुछ मिलीसेकंड रहते हैं।

इसके अलावा, कोड में हमने कॉल के बीच पिड्स को बचाने के लिए 2 फ़ंक्शंस जोड़े: restore_processors_state() और save_processors_state()। हमने वहां redis का उपयोग किया है, लेकिन आप फ़ाइलों पर कार्यान्वयन का उपयोग करने का निर्णय ले सकते हैं।

हम क्रॉन का उपयोग करके हर मिनट इस स्क्रिप्ट को चलाते हैं। क्रॉन जांचता है कि क्या सभी प्रक्रियाएं जीवित हैं। यदि नहीं - तो यह उन्हें फिर से चलाता है और फिर मर जाता है। अगर हम मौजूदा प्रक्रियाओं को मारना चाहते हैं तो हम इस स्क्रिप्ट को तर्क kill: php script.php kill के साथ चलाएं।

init.d में स्क्रिप्ट इंजेक्शन के बिना श्रमिकों को चलाने का बहुत आसान तरीका।

<?php 

include_once dirname(__FILE__) . '/path/to/bootstrap.php'; 

define('WANT_PROCESSORS', 5); 
define('PROCESSOR_EXECUTABLE', '' . dirname(__FILE__) . '/path/to/worker.php'); 
set_time_limit(0); 

$run = true; 
$reload = false; 
declare(ticks = 30); 

function restore_processors_state() 
{ 
    global $processors; 

    $redis = Zend_Registry::get('redis'); 
    $pids = $redis->hget('worker_procs', 'pids'); 

    if(!$pids) 
    { 
     $processors = array(); 
    } 
    else 
    { 
     $processors = json_decode($pids, true); 
    } 
} 

function save_processors_state() 
{ 
    global $processors; 

    $redis = Zend_Registry::get('redis'); 
    $redis->hset('worker_procs', 'pids', json_encode($processors)); 
} 

function spawn_processor() { 
    $pid = pcntl_fork(); 
    if($pid) { 
     global $processors; 
     $processors[] = $pid; 
    } else { 
     if(posix_setsid() == -1) 
      die("Forked process could not detach from terminal\n"); 
     fclose(STDIN); 
     fclose(STDOUT); 
     fclose(STDERR); 
     pcntl_exec('/usr/bin/php', array(PROCESSOR_EXECUTABLE)); 
     die('Failed to fork ' . PROCESSOR_EXECUTABLE . "\n"); 
    } 
} 

function spawn_processors() { 
    restore_processors_state(); 

    check_processors(); 

    save_processors_state(); 
} 

function kill_processors() { 
    global $processors; 
    foreach($processors as $processor) 
     posix_kill($processor, SIGTERM); 
    foreach($processors as $processor) 
     pcntl_waitpid($processor, $trash); 
    unset($processors); 
} 

function check_processors() { 
    global $processors; 
    $valid = array(); 
    foreach($processors as $processor) { 
     pcntl_waitpid($processor, $status, WNOHANG); 
     if(posix_getsid($processor)) 
      $valid[] = $processor; 
    } 
    $processors = $valid; 
    if(count($processors) > WANT_PROCESSORS) { 
     for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--) 
      posix_kill($processors[$ix], SIGTERM); 
     for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--) 
      pcntl_waitpid($processors[$ix], $trash); 
    } 
    elseif(count($processors) < WANT_PROCESSORS) { 
     for($ix = count($processors); $ix < WANT_PROCESSORS; $ix++) 
      spawn_processor(); 
    } 
} 

if(isset($argv) && count($argv) > 1) { 
    if($argv[1] == 'kill') { 
     restore_processors_state(); 
     kill_processors(); 
     save_processors_state(); 

     exit(0); 
    } 
} 

spawn_processors(); 
संबंधित मुद्दे