Run parallel process in PHP

7

I have a Web service that is consumed by some applications. On the Web service server you should use the Amazon API and execute a process whenever a change of record is made via Web service .

Initially, I thought about running the Amazon process the same time I answered the user. The fact is that the Amazon service tends to take longer compared to the Web service response to applications, which could result in a time-consuming user response.

In this case, I thought of running in Threads, so whenever a request was sent to the Web service , it would initiate a parallel connection to Amazon. But there are resource restrictions on the server ( Locaweb ) and I'm not allowed to install add-ons.

<?php

class workerThread extends Thread {
    public function __construct($i){
        $this->i=$i;
    }

    public function run(){
        while(true){
            echo $this->i;
            sleep(1);
        }
    }
}

for($i=0;$i<50;$i++){
    $workers[$i]=new workerThread($i);
    $workers[$i]->start();
}

?>

Another way I thought of doing would be to run a cURL , but from what I saw, the response time is the same as running the process on the same line as Web service .

Then master gurus with PHP , you can run this communication with Amazon in the background and the response to the user is sent in the default Web service to avoid a very high response time?

    
asked by anonymous 31.03.2015 / 14:52

2 answers

9

To execute a process in parallel, follow the steps below.

You mentioned that the hosting is in Locaweb and the exec function is blocked on their Windows servers. I've seen other companies blocking this function. So this answer only works on Linux . For Windows it is possible to adapt with the code of this answer (in English) .

Create a php file with the process that should run in the background, in this example it will be thread.php

In the file that will start thread include:

exec('php diretorio/thread.php >> diretorio_logs/arquivo_de_log.log 2>&1 &');

The function exec executes on the command line the string passed as a parameter.

The >> operator saves everything thread.php display with echo ( printf , etc.) in the specified file. The 2>&1 part redirects stderr to stdout, so anything displayed by thread.php will be saved in arquivo_de_log.log . %, including any errors.

If the output of thread.php can be discarded use only:

exec('php diretorio/thread.php &');

The & at the end is responsible for starting the process execution in the background. With this modifier, the command is executed and the process that called the command does not awaits completion.

There is a PHP extension for process control that can also be used: link

    
01.04.2015 / 12:19
3

A routine that runs processes in the background:

class Background
{

    /*
    $cmd -> A linha de comando a executar.
    $opt -> Opção de parâmetros para o ambiente onde executa o script.
    */
    public static function Call($cmd, $opt = 'start')
    {

        if (stripos(php_uname('s'), 'windows') !== false) {
            /*
            Condições de parâmetros para ambiente Windows.
            */
            switch ($opt) {
                default:
                case 'start':
                    $prefix = 'start /B '; // Esse aqui é o padrão, pois é compatível com as versões mais recentes do Windows.
                    $sufix = '';
                    break;
                case 'nul':
                    $prefix = '';
                    $sufix = ' > NUL 2> NUL';
                    break;
            }
        } else {
            /*
            Opções para ambiente *nix. (isso inclui os-x)
            Normalmente o sufixo ' &' é compatível com diversas distribuições Linux. Esse parâmetro diz ao sistema operacional executar em background.
            */
            switch ($opt) {
                default:
                case '&':
                    $prefix = '';
                    $sufix = ' &';
                    break;
                case 'dev-null':
                    $prefix = '';
                    $sufix = ' > /dev/null 2>/dev/null &';
                    break;
            }
        }

        exec(sprintf('%s%s%s', $prefix, $cmd, $sufix));

        return null;
    }

}

define('PHP_PATH', '/local/do/binario/php');

echo 'start '.microtime(true);
Background::Call(PHP_PATH.' "/local/de/um/arquivo.php"');
Background::Call(PHP_PATH.' "/local/de/um/arquivo.php"');
Background::Call(PHP_PATH.' "/local/de/um/arquivo.php"');
echo PHP_EOL.'end '.microtime(true);

file.php

<?php

/*
Fecha o output, ou seja, faz com que o script que invocou, não fique esperando por uma resposta.
*/
fclose(STDOUT);

/*
Daqui em diante, pode fazer o que bem entender.
Claro, esteja ciente de que tudo aqui está sendo executado em ambiente CLI (Command Line Interface).

Vamos fazer uma simulação e testar se está funcionando.
*/

file_put_contents('background.txt', 'start '.microtime(true).PHP_EOL, FILE_APPEND);
sleep(5); // espera 5 segundos
file_put_contents(BASE_DIR.'background.txt', 'end '.microtime(true).PHP_EOL, FILE_APPEND);

About the asynchronous execution routine

There is no process control. Basically an execution command is sent by the exec() function, which, combined with some parameters, ignores the return of a response. By doing so, asynchronous executions.

Combinations vary by environment, so be aware that it's not enough just to copy the code and think it will work like magic.

In method Call() of class Background , just add new parameters if necessary.

Example:

            /*
            Opções para ambiente *nix. (isso inclui os-x)
            Normalmente o sufixo ' &' é compatível com diversas distribuições Linux. Esse parâmetro diz ao sistema operacional executar em background.
            */

            switch ($opt) {
                default:
                case '&':
                    $prefix = '';
                    $sufix = ' &';
                    break;
                case 'dev-null':
                    $prefix = '';
                    $sufix = ' > /dev/null 2>/dev/null &';
                    break;
                case 'dev-null2':
                    $prefix = '';
                    $sufix = ' /dev/null 2>&1 &';
                    break;
                case 'outro-nome-como-quiser':
                    $prefix = '';
                    $sufix = ' /algum/comando/diferente/que/funcione/num/ambiente/especifico';
                    break;
            } 

The script is simple, clean, easy to understand. It does not depend on third-party libraries.

    
05.08.2016 / 02:15