Heim  >  Artikel  >  Backend-Entwicklung  >  Verwendung von fsockopen in PHP zur Implementierung asynchroner Anforderungen (Codebeispiel)

Verwendung von fsockopen in PHP zur Implementierung asynchroner Anforderungen (Codebeispiel)

藏色散人
藏色散人nach vorne
2020-01-22 17:44:072785Durchsuche

Verwendung von fsockopen in PHP zur Implementierung asynchroner Anforderungen (Codebeispiel)

php führt ein Programm aus. Es kann in wenigen Millisekunden abgeschlossen sein oder lange dauern.

Wenn beispielsweise ein Benutzer eine Bestellung aufgibt und einige Dienste von Drittanbietern aufgerufen werden, um E-Mails, Textnachrichten, Push-Benachrichtigungen usw. zu senden, kann das Frontend warten.

Manchmal sind uns die Rückgabeergebnisse dieser zeitaufwändigen Skripte egal, solange sie ausgeführt werden. Zu diesem Zeitpunkt müssen Sie es asynchron ausführen.

Wie wir alle wissen, unterstützt PHP Multithreading nicht direkt. Wir können es auf kompromittierte Weise tun. Hier geht es vor allem um fsockopen.

Senden Sie die Anfrage über fsockopen und ignorieren Sie das Rückgabeergebnis. Das Programm kann sofort zurückkehren.

Beispielcode:

$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "GET /backend.php   HTTP/1.1\r\n";
    $out .= "Host: www.example.com\r\n";
    $out .= "Connection: Close\r\n\r\n";
 
    fwrite($fp, $out);
    /*忽略执行结果
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }*/
    fclose($fp);
}

Es ist zu beachten, dass wir die Header-Informationen manuell buchstabieren müssen. Durch Öffnen des Kommentarbereichs können Sie das Rückgabeergebnis der Anforderung anzeigen. Diesmal wird es jedoch wieder synchron, da das Programm vor dem Beenden auf das Rückgabeergebnis wartet.

Während des eigentlichen Tests haben wir festgestellt, dass die Sockenanforderung jedes Mal erfolgreich gesendet wird, wenn wir die Ausführungsergebnisse nicht ignorieren nicht erfolgreich gesendet. Überprüfen Sie das Nginx-Protokoll und finden Sie viele Anfragen mit dem Statuscode 499.

Später habe ich den Grund gefunden:

fwrite wird unmittelbar nach fclose ausgeführt, Nginx gibt 499 direkt zurück und leitet die Anfrage nicht zur Verarbeitung an PHP weiter .

Wenn der Client eine Verbindung über den aktiven Port anfordert, leitet NGINX die Anfrage nicht an den Upstream-Dienst weiter (FastCGI PHP-Prozess). Zu diesem Zeitpunkt wird die Anfrage als 499 im Zugriffsprotokoll aufgezeichnet.

Lösung:

1) Konfiguration zu nginx.conf hinzufügen

# 忽略客户端中断
fastcgi_ignore_client_abort on;

2) Verwenden Sie usleep nach fwrite Die Funktion schläft 20 Millisekunden lang:

usleep(20000);

Später stellte der Test keinen Fehler fest.

Fügen Sie den vollständigen Code bei:

<?php
/**
 * 工具类
 * */
class FsockService {
    
    public static function post($url, $param){
        $host = parse_url($url, PHP_URL_HOST);
        $port = 80;
        $errno = &#39;&#39;;
        $errstr = &#39;&#39;;
        $timeout = 30;
        $data = http_build_query($param);
        // create connect
        $fp = fsockopen($host, $port, $errno, $errstr, $timeout);
        if(!$fp){
            return false;
        }
        // send request
        $out = "POST ${url} HTTP/1.1\r\n";
        $out .= "Host:${host}\r\n";
        $out .= "Content-type:application/x-www-form-urlencoded\r\n";
        $out .= "Content-length:".strlen($data)."\r\n";
        $out .= "Connection:close\r\n\r\n";
        $out .= "${data}";
        fwrite($fp, $out);
        //忽略执行结果;否则等待返回结果
//        if(APP_DEBUG === true){
        if(false){
            $ret = &#39;&#39;;
            while (!feof($fp)) {
                $ret .= fgets($fp, 128);
            }
        }
        usleep(20000); //fwrite之后马上执行fclose,nginx会直接返回499
        fclose($fp);
    }
    public static function get($url, $param){
        $host = parse_url($url, PHP_URL_HOST);
        $port = 80;
        $errno = &#39;&#39;;
        $errstr = &#39;&#39;;
        $timeout = 30;
        $url = $url.&#39;?&#39;.http_build_query($param);
        // create connect
        $fp = fsockopen($host, $port, $errno, $errstr, $timeout);
        if(!$fp){
            return false;
        }
        // send request
        $out = "GET ${url} HTTP/1.1\r\n";
        $out .= "Host:${host}\r\n";
        $out .= "Connection:close\r\n\r\n";
        fwrite($fp, $out);
        //忽略执行结果;否则等待返回结果
//        if(APP_DEBUG === true){
        if(false){
            $ret = &#39;&#39;;
            while (!feof($fp)) {
                $ret .= fgets($fp, 128);
            }
        }
        usleep(20000); //fwrite之后马上执行fclose,nginx会直接返回499
        fclose($fp);
    }
   
}
?>

Weitere PHP-Kenntnisse finden Sie im PHP-Tutorial!

Das obige ist der detaillierte Inhalt vonVerwendung von fsockopen in PHP zur Implementierung asynchroner Anforderungen (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen