Comment peut-on utiliser multi threading dans les applications PHP

y a-t-il une façon réaliste d'implémenter un modèle multi-threadé en PHP que ce soit vraiment, ou simplement en le simulant. Il y a quelque temps, il a été suggéré que vous pourriez forcer le système d'exploitation à charger une autre instance de L'exécutable PHP et gérer d'autres processus simultanés.

le problème avec cela est que lorsque le code PHP a terminé l'exécution de L'instance PHP reste en mémoire parce qu'il n'y a aucun moyen de la tuer à partir de PHP. Donc si vous êtes à la simulation plusieurs fils que vous pouvez imaginer ce qui va se passer. Je suis donc toujours à la recherche d'un moyen de multi-threading peut être fait ou simulé efficacement à partir de PHP. Des idées?

330
demandé sur Lance Roberts 2008-09-16 13:56:31

18 réponses

Multi-threading est possible en php

Oui vous pouvez faire du multi-threading dans PHP avec pthreads

à Partir de la documentation PHP :

pthreads est une API orientée objet qui fournit tous les outils nécessaires pour multi-threading en PHP. Les applications PHP peuvent créer, lire, écrire, exécuter et synchroniser avec les Threads, Les ouvriers et les objets filetés.

Avertissement : L'extension pthreads ne peut pas être utilisée dans un environnement de serveur web. Le Threading en PHP doit donc rester réservé aux applications CLI.

Test Simple

#!/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();
}

?>

Première

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

Deuxième Manche

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

Exemple Du Monde Réel

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);
}
361
répondu Baba 2017-07-06 17:57:28

pourquoi n'utilisez-vous pas 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]);
    }
}
26
répondu masterb 2017-09-01 12:31:00

Threading n'est pas disponible en PHP stock, mais la programmation simultanée est possible en utilisant des requêtes HTTP comme appels asynchrones.

avec le paramètre timeout de curl réglé à 1 et en utilisant le même session_id pour les processus que vous voulez être associés les uns aux autres, vous pouvez communiquer avec les variables de session comme dans mon exemple ci-dessous. Avec cette méthode, vous pouvez même fermer votre navigateur et le processus concurrent existe toujours sur le serveur.

N'oubliez pas de vérifier le bon ID de session comme ceci:

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

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"];

de fabrication1.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);
15
répondu Ricardo 2011-12-26 05:17:04

même si vous ne pouvez pas fileter, vous avez un certain degré de contrôle du processus en php. Les deux ensembles de fonctions qui sont utiles ici sont:

fonctions de commande de processus http://www.php.net/manual/en/ref.pcntl.php

fonctions POSIX http://www.php.net/manual/en/ref.posix.php

vous pouvez bifurquer votre processus avec pcntl_fork - retour le PID de l'enfant. Ensuite, vous pouvez utiliser posix_kill pour se débarrasser de ce PID.

cela dit, si vous tuez un processus parent, un signal doit être envoyé au processus enfant lui disant de mourir. Si php lui-même ne le reconnaît pas, vous pouvez enregistrer une fonction pour la gérer et faire une sortie propre en utilisant pcntl_signal.

10
répondu J.D. Fitz.Gerald 2008-09-16 10:30:11

l'utilisation de filets est rendue possible par l'extension PECL de pthreads

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

8
répondu pinkal vansia 2013-10-31 18:07:50

je sais que c'est une vieille question mais pour les gens qui cherchent, il y a une extension PECL écrite en C qui donne la capacité de multi-threading PHP maintenant, il est situé ici https://github.com/krakjoe/pthreads

8
répondu JasonDavis 2015-01-07 19:33:34

vous pouvez simuler un filetage. PHP peut exécuter des processus de fond via popen (ou proc_open). Ces processus peuvent être communiqués via stdin et stdout. Bien sûr, ces processus peuvent eux-mêmes être un programme php. C'est probablement aussi proche que vous obtiendrez.

5
répondu Pete 2010-08-26 21:33:57

vous pouvez utiliser exec() pour exécuter un script en ligne de commande (tel que la ligne de commande php), et si vous pipez la sortie vers un fichier, alors votre script n'attendra pas que la commande soit terminée.

Je ne me souviens pas très bien de la syntaxe de php CLI, mais vous voulez quelque chose comme:

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

je pense que pas mal de serveurs d'hébergement mutualisés ont désactivé exec() par défaut pour des raisons de sécurité, mais pourrait être intéressant d'essayer.

4
répondu Adam Hopkinson 2015-09-13 18:34:54

selon ce que vous essayez de faire, vous pouvez également utiliser curl_multi pour y parvenir.

3
répondu Sheldmandu 2011-01-25 04:45:09

je sais que c'est vieux, mais vous pourriez regarder http://phpthreadlib.sourceforge.net/

il prend en charge la communication bi-directionnelle inter-thread et a également des protections intégrées pour tuer les fils d'enfant (prévenir les orphelins).

3
répondu Unsigned 2011-02-23 15:13:59

vous pouvez avoir l'option de:

  1. multi_curl
  2. on peut utiliser la commande système pour le même
  3. scénario idéal est, créer une fonction de threading en langage C et compiler/configurer en PHP. Maintenant cette fonction sera la fonction de PHP.
2
répondu Manoj Donga 2011-05-11 06:37:28

Que Diriez-vous de pcntl_fork?

consultez notre page de manuel pour des exemples: PHP pcntl_fork

2
répondu Jarrod 2012-01-13 00:55:28

la "classe de filetage 151910920" est disponible depuis les fiches de données de sécurité ≥ 2.0.0.

2
répondu Dhananjay Kashyap 2016-11-21 01:13:12

pcntl_fork ne fonctionnera pas dans un environnement de serveur web s'il a mode de sécurité activé. Dans ce cas, il ne fonctionnera que dans la version CLI de PHP.

2
répondu Stilero 2017-09-10 10:33:46

pour la multithreading HTTP en utilisant GuzzleHttp (comme les pthreads peuvent ne pas fonctionner dans les applications web), s'il vous plaît voir ci-dessous blog - https://blog.madewithlove.be/post/concurrent-http-requests/

0
répondu Som 2018-02-09 08:48:48

au moment de l'écriture de mon commentaire actuel, Je ne suis pas au courant des threads PHP. Je suis venu pour chercher la réponse ici moi-même, mais une solution de rechange est que le programme PHP qui reçoit la demande du serveur web délègue la formulation de la réponse entière à une application console qui stocke sa sortie, la réponse à la demande, à un fichier binaire et le programme PHP qui a lancé l'application console renvoie ce fichier binaire octet par octet comme la réponse à la demande reçue. Le l'application de la console peut être écrite dans n'importe quel langage de programmation qui tourne sur le serveur, y compris ceux qui ont le soutien de filetage approprié, y compris les programmes C++ qui utilisent OpenMP.

un truc pas fiable, sale, est D'utiliser PHP pour exécuter une application de console, "uname",

uname -a

et d'Imprimer la sortie de cette commande de console à la sortie HTML pour trouver la version exacte du logiciel serveur. Puis installez la même version de la logiciel à une instance VirtualBox, compiler / assembler tout ce qui est entièrement autonome, de préférence statique, les binaires que l'on veut et les télécharger ensuite sur le serveur. A partir de ce moment, L'application PHP peut utiliser ces binaires dans le rôle de l'application console qui a le bon multi-threading. C'est une solution sale, peu fiable, pour contourner une situation, quand l'administrateur du serveur n'a pas installé toutes les implémentations de langage de programmation nécessaires sur le serveur. La chose à regarder dehors pour est qu'à chaque requête que L'application PHP reçoit la(les) application (s) console se termine/exit/get_alilled.

quant à ce que les administrateurs de services d'hébergement pensent de tels modèles d'utilisation de serveur, je suppose que cela se résume à la culture. En Europe du Nord, le fournisseur de services doit fournir ce qui a été annoncé et si l'exécution des commandes de la console a été autorisée et le téléchargement de fichiers non malveillants a été autorisé et le fournisseur de services a le droit de tuer tout processus serveur après un quelques minutes ou même après 30 secondes, puis le service d'hébergement administrateurs manque d'arguments pour former une bonne plainte. Aux Etats-Unis et en Europe de l'Ouest la situation / culture est très différente et je crois qu'Il ya une grande chance que dans les Etats-Unis et/ou en Europe de l'ouest le fournisseur de services d'hébergement sera refusez de servir les clients du service d'hébergement qui utilisent l'astuce décrite ci-dessus. C'est juste mon avis, compte tenu de mon expérience personnelle avec les services d'hébergement aux États-Unis et compte tenu de ce que j'ai entendu parler des services d'hébergement en Europe occidentale. Au moment où j'écris mon commentaire actuel(2018_09_01), Je ne sais rien des normes culturelles des fournisseurs de services d'hébergement D'Europe du Sud, des administrateurs de réseaux D'Europe du Sud.

0
répondu Martin Vahi 2018-09-01 05:40:13

Peut-être que j'ai manqué quelque chose, mais exec n'a pas travaillé comme asynchrones pour moi dans l'environnement de windows, j'ai utilisé windows, et cela a fonctionné comme un charme ;)

$script_exec = "c:/php/php.exe c:/path/my_ascyn_script.php";

pclose(popen("start /B ". $script_exec, "r"));
-2
répondu Mubashar Ahmad 2013-10-03 05:39:52

Multithreading signifie effectuer plusieurs tâches ou processus simultanément, nous pouvons atteindre cet objectif en php en utilisant le code suivant,bien qu'il n'y ait pas de moyen direct d'atteindre le multithreading en php, mais nous pouvons atteindre presque les mêmes résultats en suivant la voie.

chdir(dirname(__FILE__));  //if you want to run this file as cron job
 for ($i = 0; $i < 2; $i += 1){
 exec("php test_1.php $i > test.txt &");
 //this will execute test_1.php and will leave this process executing in the background and will go         

 //to next iteration of the loop immediately without waiting the completion of the script in the   

 //test_1.php , $i  is passed as argument .

}

Test_1.151930920 php"

$conn=mysql_connect($host,$user,$pass);
$db=mysql_select_db($db);
$i = $argv[1];  //this is the argument passed from index.php file
for($j = 0;$j<5000; $j ++)
{
mysql_query("insert  into  test   set

                id='$i',

                comment='test',

                datetime=NOW() ");

}

exécute test_1.php deux fois simultanément et les deux processus s'exécuteront en arrière-plan simultanément, de cette façon, vous pouvez réaliser le multithreading en php.

Ce mec fait vraiment du bon travail Multithreading en php

-3
répondu Pir Abdul 2015-04-15 04:59:36