2015-11-17 2 views
3

Я использую PHP-FPM для запуска приложения Phalcon и только что установил pthreads, поэтому я могу запускать задачи асинхронно. В настоящее время я Pthreads работы с помощью интерфейса командной строки:PHP-FPM и pthreads

<?php 

/** 
* Author: Abu Ashraf Masnun 
* URL: http://masnun.me 
*/ 

class WorkerThreads extends Thread 
{ 
    private $workerId; 

    public function __construct($id) 
    { 
     $this->workerId = $id; 
    } 

    public function run() 
    { 
     usleep(2000000); // 2 seconds 
     echo "Worker {$this->workerId} ran" . PHP_EOL; 
    } 
} 

// Worker pool 
$workers = []; 

// Initialize and start the threads 
foreach (range(0, 5) as $i) { 
    $workers[$i] = new WorkerThreads($i); 
    $workers[$i]->start(); 
} 

// Let the threads come back 
foreach (range(0, 5) as $i) { 
    $workers[$i]->join(); 
} 

die('finished'); 

^^ все это работает под управлением php test.php из оболочки.

Но я не могу заставить этот пример работать с помощью быстрого диспетчера процессов. У меня есть контроллер, инициализирующий объект потока и вызывающий start(), но ни одна из логических функций в методе run() не выполняется.

Контроллер:

<?php 

public function indexAction() 
{ 

$threads=[]; 
for ($i = 0; $i < 2; $i++) 
{ 
    $threads[$i] = new AsyncThread(); 
    $a = $threads[$i]->start(); 
    $b = $threads[$i]->isStarted(); 
    Phalcon\DI::getDefault()->get('logger')->log(json_encode($a)); 
    Phalcon\DI::getDefault()->get('logger')->log(json_encode($b)); 
} 
for ($i = 0; $i < 2; $i++) 
{ 
    $threads[$i]->join(); 
} 
die('done'); 

AsyncThread.php:

<?php 

class AsyncThread extends Thread 
{ 

    public function __construct() 
    { 
     Phalcon\DI::getDefault()->get('logger')->log('construct'); 
    } 

    public function run() 
    { 
     usleep(2000000); // 2 seconds 
     Phalcon\DI::getDefault()->get('logger')->log('running'); 
    } 

} 

Когда это работает мои журналы показывают:

[Tue, 17 Nov 15 22:10:43 +0000][INFO][][] construct 
[Tue, 17 Nov 15 22:10:43 +0000][INFO][][] true 
[Tue, 17 Nov 15 22:10:43 +0000][INFO][][] true 
[Tue, 17 Nov 15 22:10:43 +0000][INFO][][] construct 
[Tue, 17 Nov 15 22:10:43 +0000][INFO][][] true 
[Tue, 17 Nov 15 22:10:43 +0000][INFO][][] true 

я ожидал увидеть 'работает' войти в асинхронном режиме, но никогда не регистрируется вообще.

Моя цель состоит в том, чтобы просто получить приветственный пример примеров posix, работающих с PHP-FPM, поэтому я могу приступить к созданию хорошо продуманного решения для моих нужд.

ответ

6

Если вы используете старую версию PHP и pthreads (< PHP7), то потоки будут выполняться без правильной установки stdout (поскольку FPM и Zend не могут установить его).

Самые последние версии pthreads (для PHP7) запрещают выполнение в любом месте, кроме CLI.

Невозможно эффективно использовать потоки во внешнем интерфейсе приложения.

Рассмотрим случай, когда контроллер, который создает достаточное количество потоков, скажем 8. Если 100 клиентов запрашивать контроллер одновременно, вы будете просить аппаратное обеспечение для выполнения 800 ядра темы одновременно с крошечного количество трафик.

Этот вид архитектуры не может шкала.

Вы настойчиво использовали слово асинхронное вместо параллельного, это заставляет меня думать, что вы, вероятно, не хотите потоков вообще.

Если задача состоит в том, чтобы сделать некоторые асинхронные веб-запросы, тогда лучший способ сделать это с неблокирующими вводами/выводами, - не темы.

Если вы используете слово асинхронно неправильно и фактически имеете в виду параллель, тогда вам нужно будет найти другой способ для тех частей приложения, которые необходимы для масштабирования с веб-сервером, и тех частей приложения, которые требуют параллельного параллелизма для связи друг с другом.