it-swarm-pt.tech

Como se pode usar multi-threading em PHP aplicações

Existe uma maneira realista de implementar um modelo multi-threaded em PHP verdadeiramente, ou apenas simulando-o. Algum tempo atrás, foi sugerido que você poderia forçar o sistema operacional a carregar outra instância do executável PHP e lidar com outros processos simultâneos.

O problema com isso é que quando o código PHPterminou a execução da instância PHP permanece na memória porque não há como eliminá-lo de dentro do PHP. Então, se você está simulando vários segmentos, pode imaginar o que vai acontecer. Então eu ainda estou procurando uma maneira de multi-threading pode ser feito ou simulado de forma eficaz a partir do PHP. Alguma ideia?

366
Steve Obbayi

Multi-threading é possível em php

Sim você pode fazer multi-threading em PHP com pthreads

De o PHP documentação :

pthreads é uma API orientada a objetos que fornece todas as ferramentas necessárias para multi-threading no PHP. PHP aplicações podem criar, ler, escrever, executar e sincronizar com Threads, Workers e objetos Threaded.

Aviso : A extensão pthreads não pode ser usada em um ambiente de servidor da web. Encadeamento em PHP deve, portanto, permanecer apenas para aplicativos baseados em CLI.

Teste simples

#!/usr/bin/php
<?php
class AsyncOperation extends Thread {

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

    public function run() {
        if ($this->arg) {
            $sleep = mt_Rand(1, 10);
            printf('%s: %s  -start -sleeps %d' . "\n", date("g:i:sa"), $this->arg, $sleep);
            sleep($sleep);
            printf('%s: %s  -finish' . "\n", date("g:i:sa"), $this->arg);
        }
    }
}

// Create a array
$stack = array();

//Initiate Multiple Thread
foreach ( range("A", "D") as $i ) {
    $stack[] = new AsyncOperation($i);
}

// Start The Threads
foreach ( $stack as $t ) {
    $t->start();
}

?>

Primeira corrida

12:00:06pm:     A  -start -sleeps 5
12:00:06pm:     B  -start -sleeps 3
12:00:06pm:     C  -start -sleeps 10
12:00:06pm:     D  -start -sleeps 2
12:00:08pm:     D  -finish
12:00:09pm:     B  -finish
12:00:11pm:     A  -finish
12:00:16pm:     C  -finish

Segunda corrida

12:01:36pm:     A  -start -sleeps 6
12:01:36pm:     B  -start -sleeps 1
12:01:36pm:     C  -start -sleeps 2
12:01:36pm:     D  -start -sleeps 1
12:01:37pm:     B  -finish
12:01:37pm:     D  -finish
12:01:38pm:     C  -finish
12:01:42pm:     A  -finish

Exemplo do mundo real

error_reporting(E_ALL);
class AsyncWebRequest extends Thread {
    public $url;
    public $data;

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

    public function run() {
        if (($url = $this->url)) {
            /*
             * If a large amount of data is being requested, you might want to
             * fsockopen and read using usleep in between reads
             */
            $this->data = file_get_contents($url);
        } else
            printf("Thread #%lu was not provided a URL\n", $this->getThreadId());
    }
}

$t = microtime(true);
$g = new AsyncWebRequest(sprintf("http://www.google.com/?q=%s", Rand() * 10));
/* starting synchronization */
if ($g->start()) {
    printf("Request took %f seconds to start ", microtime(true) - $t);
    while ( $g->isRunning() ) {
        echo ".";
        usleep(100);
    }
    if ($g->join()) {
        printf(" and %f seconds to finish receiving %d bytes\n", microtime(true) - $t, strlen($g->data));
    } else
        printf(" and %f seconds to finish, request failed\n", microtime(true) - $t);
}
391
Baba

por que você não usa popen ?

for ($i=0; $i<10; $i++) {
    // open ten processes
    for ($j=0; $j<10; $j++) {
        $pipe[$j] = popen('script2.php', 'w');
    }

    // wait for them to finish
    for ($j=0; $j<10; ++$j) {
        pclose($pipe[$j]);
    }
}
34
masterb

A segmentação não está disponível em PHP, mas a programação simultânea é possível usando solicitações HTTP como chamadas assíncronas.

Com a configuração de tempo limite do curl definida como 1 e usando o mesmo session_id para os processos aos quais você deseja se associar, é possível se comunicar com variáveis ​​de sessão, como no meu exemplo abaixo. Com esse método, você pode até fechar o navegador e o processo simultâneo ainda existe no servidor.

Não se esqueça de verificar o ID da sessão correta assim:

http: //localhost/test/verifysession.php? sessionid = [o id correto]

startprocess.php

$request = "http://localhost/test/process1.php?sessionid=".$_REQUEST["PHPSESSID"];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_exec($ch);
curl_close($ch);
echo $_REQUEST["PHPSESSID"];

process1.php

set_time_limit(0);

if ($_REQUEST["sessionid"])
   session_id($_REQUEST["sessionid"]);

function checkclose()
{
   global $_SESSION;
   if ($_SESSION["closesession"])
   {
       unset($_SESSION["closesession"]);
       die();
   }
}

while(!$close)
{
   session_start();
   $_SESSION["test"] = Rand();
   checkclose();
   session_write_close();
   sleep(5);
}

verifysession.php

if ($_REQUEST["sessionid"])
    session_id($_REQUEST["sessionid"]);

session_start();
var_dump($_SESSION);

closeprocess.php

if ($_REQUEST["sessionid"])
    session_id($_REQUEST["sessionid"]);

session_start();
$_SESSION["closesession"] = true;
var_dump($_SESSION);
18
Ricardo

Enquanto você não pode thread, você tem algum grau de controle de processo em php. Os dois conjuntos de funções que são úteis aqui são:

Funções de controle de processo http://www.php.net/manual/en/ref.pcntl.php

Funções POSIX http://www.php.net/manual/en/ref.posix.php

Você poderia desembolsar seu processo com pcntl_fork - retornando o PID da criança. Então você pode usar posix_kill para despose desse PID.

Dito isto, se você matar um processo pai, um sinal deve ser enviado para o processo infantil, dizendo-lhe para morrer. Se o próprio php não estiver reconhecendo isso, você poderia registrar uma função para gerenciá-lo e fazer uma saída limpa usando pcntl_signal.

11
J.D. Fitz.Gerald

Eu sei que esta é uma questão antiga, mas para pessoas que pesquisam, existe uma extensão PECL escrita em C que dá PHP capacidade multi-threading agora, ela está localizada aqui https://github.com/ krakjoe/pthreads

8
JasonDavis

o uso de threads é possível graças à extensão PECL pthreads

http://www.php.net/manual/en/book.pthreads.php

8
pinkal vansia

Você poderia simular segmentação. PHP pode executar processos em segundo plano via popen (ou proc_open). Esses processos podem ser comunicados via stdin e stdout. Claro que esses processos podem ser um programa php. Isso é provavelmente o mais próximo que você conseguirá.

5
Pete

Você pode usar exec () para executar um script de linha de comando (como a linha de comando php) e, se enviar a saída para um arquivo, o script não esperará a conclusão do comando.

Não consigo me lembrar da sintaxe CLI do PHP, mas você gostaria de algo como:

exec("/path/to/php -f '/path/to/file.php' | '/path/to/output.txt'");

Acho que alguns servidores de hospedagem compartilhada têm o exec () desabilitado por padrão por motivos de segurança, mas pode valer a pena tentar.

5
Adam Hopkinson

Como sobre pcntl_fork?

veja nossa página de manual para exemplos: PHP pcntl_fork

3
Jarrod

Dependendo do que você está tentando fazer, você também pode usar o curl_multi para alcançá-lo.

3
Sheldmandu

Eu sei que isso é muito antigo, mas você pode ver http://phpthreadlib.sourceforge.net/

Ele suporta comunicação inter-thread bidirecional e também possui proteções embutidas para matar threads filhas (prevenindo órfãos).

3
Unsigned

pcntl_fork não funcionará em um ambiente de servidor da Web se tiver modo de segurança ativado. Neste caso, funcionará apenas na versão CLI do PHP.

2
Stilero

Você pode ter a opção de:

  1. multi_curl
  2. Pode-se usar o comando do sistema para o mesmo
  3. O cenário ideal é criar uma função de threading na linguagem C e compilar/configurar no PHP. Agora essa função será a função do PHP.
2
Manoj Donga

O classe Thread está disponível desde PECL pthreads ≥ 2.0.0.

2
Dhananjay Kashyap

A partir da escrita do meu comentário atual, eu não sei sobre os tópicos PHP. Eu mesmo vim procurar a resposta aqui, mas uma solução é que o programa PHP que recebe a solicitação do servidor da web delega toda a formulação de resposta a um aplicativo de console que armazena sua saída, a resposta à solicitação, para um arquivo binário e o programa PHP que lançou o aplicativo de console retorna esse arquivo binário byte por byte como a resposta para a solicitação recebida. O aplicativo de console pode ser escrito em qualquer linguagem de programação executada no servidor, incluindo aqueles que possuem suporte de encadeamento adequado, incluindo programas C++ que usam o OpenMP.

Um truque não confiável, sujo, é usar PHP para executar um aplicativo de console, "uname",

uname -a

e imprima a saída desse comando do console para a saída HTML para descobrir a versão exata do software do servidor. Em seguida, instale a mesma versão exata do software em uma instância do VirtualBox, compile/monte os binários totalmente autocontidos, preferencialmente estáticos, que desejar e, em seguida, carregue-os no servidor. A partir desse ponto, o aplicativo PHP pode usar esses binários no papel do aplicativo de console que possui multi-threading apropriado. É uma solução alternativa, suja e não confiável para uma situação, quando o administrador do servidor não instalou todas as implementações de linguagem de programação necessárias no servidor. O que deve ser observado é que, a cada solicitação que o aplicativo PHP recebe, o (s) aplicativo (s) de console é finalizado/exit/get_killed.

Quanto ao que os administradores de serviço de hospedagem pensam desses padrões de uso de servidor, acho que se resume à cultura. No Norte da Europa, o provedor de serviços tem de fornecer o que foi anunciado e se a execução de comandos do console foi permitida e o upload de arquivos não-malware foi permitido e o provedor de serviços tem o direito de matar qualquer processo do servidor após alguns minutos ou mesmo após 30 segundos Em seguida, os administradores do serviço de hospedagem não têm argumentos para formar uma reclamação adequada. Nos Estados Unidos e na Europa Ocidental, a situação/cultura é muito diferente e acredito que há uma grande chance de que nos EUA e/ou na Europa Ocidental o provedor de serviços de hospedagem se recuse a servir clientes de serviço de hospedagem que usem o truque descrito acima. Esse é apenas o meu palpite, dada a minha experiência pessoal com os serviços de hospedagem dos EUA e dado o que ouvi de outros sobre os serviços de hospedagem da Europa Ocidental. No momento da redação do meu comentário atual (2018_09_01), eu não sei nada sobre as normas culturais dos provedores de serviços de hospedagem do sul da Europa, os administradores de redes do sul da Europa.

0
Martin Vahi