it-swarm.com.de

Einstellen des Curl-Timeouts in PHP

Ich führe eine Curl-Anfrage für eine eXist-Datenbank über PHP aus. Das Dataset ist sehr groß, und die Datenbank benötigt daher regelmäßig viel Zeit, um eine XML-Antwort zurückzugeben. Um dies zu beheben, richten wir eine Curl-Anfrage mit einer angeblich langen Wartezeit ein.

$ch = curl_init();
$headers["Content-Length"] = strlen($postString);
$headers["User-Agent"] = "Curl/1.0";

curl_setopt($ch, CURLOPT_URL, $requestUrl);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, 'admin:');
curl_setopt($ch,CURLOPT_TIMEOUT,1000);
$response = curl_exec($ch);
curl_close($ch);

Die Aufrollanforderung endet jedoch konsistent, bevor die Anforderung abgeschlossen ist (<1000, wenn sie über einen Browser angefordert wird). Weiß jemand, ob dies der richtige Weg ist, um Zeitüberschreitungen im Curl festzulegen?

205
Moki

Siehe Dokumentation: http://www.php.net/manual/en/function.curl-setopt.php

CURLOPT_CONNECTTIMEOUT - Die Anzahl der Sekunden, die gewartet werden muss, während versucht wird, eine Verbindung herzustellen. Verwenden Sie 0, um auf unbestimmte Zeit zu warten.
CURLOPT_TIMEOUT - Die maximale Anzahl von Sekunden, die cURL-Funktionen ausgeführt werden dürfen.

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); 
curl_setopt($ch, CURLOPT_TIMEOUT, 400); //timeout in seconds

vergessen Sie auch nicht, die Ausführung des PHP-Skripts selbst zu verlängern:

set_time_limit(0);// to infinity for example
311
msangel

Hmm, für mich sieht es so aus, als ob CURLOPT_TIMEOUT Die Zeit definiert, die eine cURL-Funktion zur Ausführung benötigt. Ich denke, Sie sollten sich stattdessen CURLOPT_CONNECTTIMEOUT Ansehen, da dies cURL die maximale Wartezeit für den Abschluss der Verbindung vorgibt.

56
Chad Birch

Ihr Code setzt das Timeout auf 1000 Sekunden. Verwenden Sie für Millisekunden CURLOPT_TIMEOUT_MS.

26
Matt Humphreys

Es gibt eine Besonderheit, die für manche Leute relevant sein könnte ... Aus den PHP docs-Kommentaren.

Wenn cURL in weniger als einer Sekunde abgelaufen sein soll, können Sie CURLOPT_TIMEOUT_MS, obwohl es auf "Unix-ähnlichen Systemen" einen Bug/"feature" gibt, der das Timeout von libcurl sofort auslöst, wenn der Wert <1000 ms mit dem Fehler "cURL Error (28): Timeout was reached" ist. Die Erklärung für dieses Verhalten lautet:

"Wenn libcurl für die Verwendung des Standard-Systemnamensauflösers entwickelt wurde, verwendet dieser Teil der Übertragung für Zeitüberschreitungen eine Auflösung von einer vollen Sekunde, wobei eine Zeitüberschreitung von mindestens einer Sekunde zulässig ist."

Für PHP Entwickler bedeutet dies: "Sie können diese Funktion nicht verwenden, ohne sie zuerst zu testen, da Sie nicht feststellen können, ob libcurl den Standard-Systemnamen-Resolver verwendet (aber Sie können hübsch sein) Sicher ist es das)"

Das Problem ist, dass unter (Li | U) nix, wenn libcurl den Standardnamensauflöser verwendet, während der Namensauflösung ein SIGALRM ausgelöst wird, den libcurl als Timeout-Alarm ansieht.

Die Lösung besteht darin, Signale mit CURLOPT_NOSIGNAL zu deaktivieren. Hier ist ein Beispielskript, das sich selbst anfordert und eine Verzögerung von 10 Sekunden verursacht, damit Sie Timeouts testen können:

if (!isset($_GET['foo'])) {
    // Client
    $ch = curl_init('http://localhost/test/test_timeout.php?foo=bar');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
    $data = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);

    if ($curl_errno > 0) {
        echo "cURL Error ($curl_errno): $curl_error\n";
    } else {
        echo "Data received: $data\n";
    }
} else {
    // Server
    sleep(10);
    echo "Done.";
}

Von http://www.php.net/manual/en/function.curl-setopt.php#104597

26
Simon East

Sie müssen sicherstellen, dass zwischen Ihnen und der Datei Zeitüberschreitungen auftreten. In diesem Fall PHP und Curl.

Damit Curl keine Zeitüberschreitung erhält, wenn eine Übertragung noch aktiv ist, müssen Sie CURLOPT_TIMEOUT Anstelle von 0 Auf 1000 Setzen.

curl_setopt($ch, CURLOPT_TIMEOUT, 0);

In PHP müssen Sie wieder Zeitlimits entfernen oder PHP= automatisch (standardmäßig nach 30 Sekunden) beendet das Skript gemäß Curls Anforderung. Dies allein sollte Ihr Problem beheben =.
Wenn Sie außerdem Datenintegrität benötigen, können Sie mit ignore_user_abort Eine Sicherheitsebene hinzufügen:

# The maximum execution time, in seconds. If set to zero, no time limit is imposed.
set_time_limit(0);

# Make sure to keep alive the script when a client disconnect.
ignore_user_abort(true);

Eine Client-Trennung unterbricht die Ausführung des Skripts und kann möglicherweise Daten beschädigen.
z.B. Nicht-Übergangs-Datenbankabfrage, Erstellen einer Konfigurationsdatei usw., während in Ihrem Fall eine Teildatei heruntergeladen würde ... und Sie sich darum kümmern könnten oder nicht.

Beantwortung dieser alten Frage, da dieser Thread bei Suchmaschinen nach CURL_TIMEOUT Ganz oben steht.

10
MarcoP

Sie können die Anforderung nicht über einen Browser ausführen. Es tritt eine Zeitüberschreitung auf, wenn der Server, auf dem die CURL-Anforderung ausgeführt wird, antwortet. Das Zeitlimit des Browsers liegt wahrscheinlich bei 1-2 Minuten, dem Standard-Netzwerk-Timeout.

Sie müssen es über die Befehlszeile/das Terminal ausführen.

8
Brent Baisley

Wenn Sie PHP als FastCGI-Anwendung verwenden, stellen Sie sicher, dass Sie die FastCGI-Timeout-Einstellungen überprüfen. Siehe: PHP-Curl-Put-500-Fehler

3
wbinky