it-swarm-eu.dev

Wie kann man Multi-Threading in PHP -Anwendungen verwenden?

Gibt es eine realistische Möglichkeit, ein Multithread-Modell in PHP zu implementieren, sei es tatsächlich oder einfach nur zu simulieren? Vor einiger Zeit wurde vorgeschlagen, das Betriebssystem zu zwingen, eine andere Instanz der ausführbaren Datei PHP zu laden und andere gleichzeitige Prozesse zu verarbeiten.

Das Problem dabei ist, dass, wenn der PHP - Code die Ausführung der PHP - Instanz beendet hat, diese im Speicher verbleibt, da es keine Möglichkeit gibt, sie in PHP zu beenden. Wenn Sie also mehrere Threads simulieren, können Sie sich vorstellen, was passieren wird. Daher suche ich immer noch nach einer Möglichkeit, Multithreading in PHP effektiv durchzuführen oder zu simulieren. Irgendwelche Ideen?

374
Steve Obbayi

Multithreading ist in PHP möglich

Ja, Sie können Multi-Threading in PHP mit pthreads ausführen

From die PHP Dokumentation :

pthreads ist eine objektorientierte API, die alle Tools für das Multithreading in PHP bereitstellt. PHP -Anwendungen können Threads, Worker- und Threaded-Objekte erstellen, lesen, schreiben, ausführen und synchronisieren.

Warnung : Die Erweiterung "pthreads" kann in einer Webserverumgebung nicht verwendet werden. Das Threading in PHP sollte daher nur für CLI-basierte Anwendungen verwendet werden.

Einfacher Test

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

?>

Erster Lauf

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

Zweiter Lauf

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

Beispiel aus der realen Welt

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);
}
397
Baba

warum benutzt du nicht 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]);
    }
}
37
masterb

Threading ist in Standard-PHP nicht verfügbar, aber gleichzeitige Programmierung ist möglich, indem HTTP-Anforderungen als asynchrone Aufrufe verwendet werden.

Wenn die Zeitlimiteinstellung der Locke auf 1 festgelegt ist und für die Prozesse, die miteinander verknüpft werden sollen, dieselbe Sitzungs-ID verwendet wird, können Sie mit Sitzungsvariablen wie im folgenden Beispiel kommunizieren. Mit dieser Methode können Sie sogar Ihren Browser schließen und der gleichzeitige Prozess ist noch auf dem Server vorhanden.

Vergessen Sie nicht, die richtige Sitzungs-ID wie folgt zu überprüfen:

http: //localhost/test/verifysession.php? sessionid = [the korrekte 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"];

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);
20
Ricardo

Obwohl Sie kein Threading durchführen können, haben Sie in PHP einen gewissen Grad an Prozesskontrolle. Die beiden hier nützlichen Funktionssätze sind:

Prozesssteuerungsfunktionen http://www.php.net/manual/en/ref.pcntl.php

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

Sie könnten Ihren Prozess mit pcntl_fork verzweigen - die PID des Kindes zurückgeben. Dann können Sie posix_kill verwenden, um diese PID zu beseitigen.

Das heißt, wenn Sie einen übergeordneten Prozess beenden, sollte ein Signal an den untergeordneten Prozess gesendet werden, das ihn auffordert, zu sterben. Wenn PHP selbst dies nicht erkennt, können Sie eine Funktion registrieren, um es zu verwalten und mit pcntl_signal einen sauberen Exit durchzuführen.

11

die Verwendung von Threads wird durch die PECL-Erweiterung pthreads ermöglicht

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

10
pinkal vansia

Ich weiß, dass dies eine alte Frage ist, aber für Suchende gibt es eine in C geschriebene PECL-Erweiterung, die PHP Multithreading-Fähigkeit bietet. Sie befindet sich hier https://github.com/ krakjoe/pthreads

9
JasonDavis

Sie können exec () verwenden, um ein Befehlszeilenskript (z. B. Befehlszeilen-PHP) auszuführen. Wenn Sie die Ausgabe in eine Datei umleiten, wartet Ihr Skript nicht auf den Abschluss des Befehls.

Ich kann mich nicht ganz an die PHP-CLI-Syntax erinnern, aber Sie möchten etwas wie:

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

Ich denke, einige Shared-Hosting-Server haben exec () aus Sicherheitsgründen standardmäßig deaktiviert, aber es könnte einen Versuch wert sein.

6
Adam Hopkinson

Sie könnten das Einfädeln simulieren. PHP kann Hintergrundprozesse über popen (oder proc_open) ausführen. Diese Prozesse können über stdin und stdout kommuniziert werden. Natürlich können diese Prozesse selbst ein PHP-Programm sein. Das ist wahrscheinlich so nah wie möglich.

5
Pete

Wie wäre es mit pcntl_fork?

beispiele finden Sie auf der Handbuchseite: PHP pcntl_fork

<?php

    $pid = pcntl_fork();
    if ($pid == -1) {
        die('could not fork');
    } else if ($pid) {
        // we are the parent
        pcntl_wait($status); //Protect against Zombie children
    } else {
        // we are the child
    }

?>
4
Jarrod

Je nachdem, was Sie versuchen, können Sie auch curl_multi verwenden, um dies zu erreichen.

3
Sheldmandu

Ich weiß, dass dies sehr alt ist, aber Sie können sich http://phpthreadlib.sourceforge.net/ ansehen

Es unterstützt die bidirektionale Kommunikation zwischen Threads und verfügt über integrierte Schutzfunktionen zum Unterbinden von untergeordneten Threads (Verhindern von Waisenkindern).

3
Unsigned

Die Thread-Klasse ist verfügbar, da PECL-Threads ≥ 2.0.0 sind.

3

pcntl_fork funktioniert in einer Webserverumgebung nicht, wenn abgesicherter Modus aktiviert ist. In diesem Fall funktioniert es nur in der CLI-Version von PHP.

2
Stilero

Sie können folgende Optionen auswählen:

  1. multi_curl
  2. Man kann den Systembefehl dafür benutzen
  3. Ideales Szenario ist, eine Threading-Funktion in C-Sprache zu erstellen und in PHP zu kompilieren/konfigurieren. Nun wird diese Funktion die Funktion von PHP sein.
2
Manoj Donga

Zum Zeitpunkt des Schreibens meines aktuellen Kommentars sind mir die PHP -Threads nicht bekannt. Ich bin selbst gekommen, um nach der Antwort zu suchen, aber eine Problemumgehung besteht darin, dass das Programm PHP, das die Anforderung vom Webserver empfängt, die gesamte Antwortformulierung an eine Konsolenanwendung delegiert, in der die Ausgabe gespeichert wird, die Antwort an die request an eine Binärdatei und das Programm PHP, das die Konsolenanwendung gestartet hat, gibt diese Binärdatei byteweise als Antwort auf die empfangene Anforderung zurück. Die Konsolenanwendung kann in einer beliebigen Programmiersprache geschrieben werden, die auf dem Server ausgeführt wird, einschließlich derjenigen, die ordnungsgemäßes Threading unterstützen, einschließlich C++ - Programmen, die OpenMP verwenden.

Ein unzuverlässiger, schmutziger Trick besteht darin, PHP zum Ausführen einer Konsolenanwendung "uname" zu verwenden.

uname -a

und drucken Sie die Ausgabe dieses Konsolenbefehls in die HTML-Ausgabe, um die genaue Version der Serversoftware zu ermitteln. Installieren Sie dann genau die gleiche Version der Software auf einer VirtualBox-Instanz, kompilieren/montieren Sie die vollständig in sich geschlossenen, vorzugsweise statischen Binärdateien und laden Sie diese dann auf den Server hoch. Ab diesem Zeitpunkt kann die Anwendung PHP diese Binärdateien in der Rolle der Konsolenanwendung verwenden, die über ein ordnungsgemäßes Multithreading verfügt. Es ist eine schmutzige, unzuverlässige Problemumgehung, wenn der Serveradministrator nicht alle erforderlichen Programmiersprachenimplementierungen auf dem Server installiert hat. Achten Sie darauf, dass bei jeder Anforderung, dass die Anwendung PHP die Konsolenanwendung (en) empfängt,/exit/get_killed beendet wird.

Was die Hosting-Service-Administratoren von solchen Servernutzungsmustern halten, läuft vermutlich auf Kultur hinaus. In Nordeuropa MUSS DER DIENSTLEISTER ÜBERMITTELN, WAS ANGEBOTEN WURDE und ob die Ausführung von Konsolenbefehlen und das Hochladen von Nicht-Malware-Dateien zulässig war und der Dienstanbieter das Recht hat, jeden Serverprozess nach einigen Minuten oder sogar nach 30 Sekunden abzubrechen Dann haben die Hosting-Service-Administratoren keine Argumente für eine ordnungsgemäße Beschwerde. In den Vereinigten Staaten und Westeuropa ist die Situation/Kultur sehr unterschiedlich und ich glaube, dass es eine große Chance gibt, dass der Hosting-Service-Provider in den USA und/oder Westeuropa Hosting-Service-Kunden ablehnt, die den oben beschriebenen Trick anwenden. Das ist nur meine Vermutung, angesichts meiner persönlichen Erfahrung mit US-Hostingdiensten und angesichts dessen, was ich von anderen über westeuropäische Hostingdienste gehört habe. Zum Zeitpunkt des Schreibens meines aktuellen Kommentars (2018_09_01) weiß ich nichts über die kulturellen Normen der südeuropäischen Hosting-Dienstleister, der südeuropäischen Netzwerkadministratoren.

0
Martin Vahi