PHP'de Curl Zaman Aşımını Ayarlama


230

Ben php üzerinden bir eXist veritabanında bir kıvırmak isteği çalıştırıyorum. Veri kümesi çok büyüktür ve sonuç olarak, veritabanı bir XML yanıtı döndürmek için tutarlı bir şekilde uzun zaman alır. Bunu düzeltmek için, uzun bir zaman aşımı olması gereken bir kıvrılma isteği ayarladık.

$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);

Ancak bukle isteği, istek tamamlanmadan önce sürekli olarak sona erer (bir tarayıcı aracılığıyla istendiğinde <1000). Herkes bu kıvrımda zaman aşımı ayarlamak için uygun bir yol olup olmadığını biliyor mu?

Yanıtlar:


346

Belgelere bakın: http://www.php.net/manual/en/function.curl-setopt.php

CURLOPT_CONNECTTIMEOUT- Bağlanmaya çalışırken beklenecek saniye sayısı. Süresiz beklemek için 0 kullanın.
CURLOPT_TIMEOUT- cURL işlevlerinin yürütülmesine izin vermek için maksimum saniye sayısı.

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

Ayrıca php script kendini yürütme süresini büyütmeyi unutmayın:

set_time_limit(0);// to infinity for example

13
set_time_limit(0);Komut dosyasının konsolda çalışıyor olması gerekmez .
CONvid19

6
@PedroLobito bahsettiğiniz ne cli php varsayılan yapılandırma, ancak bu değiştirilmiş olabilir.
cherouvim

4
@cherouvim burada açıkça doğrudur (sadece koşmak php -d max_execution_time=1 -r 'while(true){$r=1*1;}'veya klibin sihirli bir 'her zaman sınırsız' bayrağı olmadığını gözlemlemek için bir şey
Wrikken

@Pedro Lobito set_time_limit(0)bir döngü içinde kullanmıyorsanız ihtiyacınız yoktur .
Viktor Joras

58

Hmm, bana öyle geliyor CURLOPT_TIMEOUTki herhangi bir cURL fonksiyonunun yürütülmesine izin verilen süreyi tanımlar. Bunun CURLOPT_CONNECTTIMEOUTyerine aslında cURL'a bağlantının tamamlanmasını beklemek için gereken azami süreyi bildirdiği için aslında bakmanız gerektiğini düşünüyorum .


İken PHP'de dokümanlar diyelim CURLOPT_TIMEOUTişlevi ne kadar sürdüğünü hakkındadır, altta yatan bukle kütüphane dokümanlar bu istek ilginç bir ayrım olan ne kadar sürdüğünü olduğunu söyler görünmektedir - Emin hangi yolu okumak için!
fideloper


33

Bazı insanlar için ilgili olabilecek bir tuhaflık var ... PHP dokümanlar yorumlarından.

CURL'nin bir saniyeden daha kısa bir sürede zaman aşımına uğramasını istiyorsanız CURLOPT_TIMEOUT_MS, "Unix benzeri sistemlerde" bir hata / "özellik" olmasına rağmen, değerin <1000 ms hata ile <cURL olması durumunda derhal zaman aşımına neden olur Hata (28): Zaman aşımına ulaşıldı ". Bu davranışın açıklaması:

"Libcurl standart sistem adı çözümleyicisini kullanacak şekilde oluşturulmuşsa, aktarımın bu bölümü, bir saniyeye izin verilen minimum zaman aşımı olan zaman aşımları için tam saniye çözünürlüğünü kullanmaya devam eder."

PHP geliştiricileri için bunun anlamı "İlk önce test etmeden bu işlevi kullanamazsınız, çünkü libcurl'un standart sistem adı çözümleyicisini kullanıp kullanmadığını söyleyemezsiniz (ancak bunun olduğundan emin olabilirsiniz)"

Sorun, (Li | U) nix'de, libcurl standart ad çözümleyiciyi kullandığında, ad çözümlemesi sırasında libcurl'in zaman aşımı alarmı olduğunu düşündüğü bir SIGALRM ortaya çıkar.

Çözüm CURLOPT_NOSIGNAL kullanarak sinyalleri devre dışı bırakmaktır. Aşağıda, zaman aşımlarını test edebilmeniz için 10 saniyelik bir gecikmeye neden olan bir örnek komut dosyası verilmiştir:

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.";
}

Gönderen http://www.php.net/manual/en/function.curl-setopt.php#104597


Merhaba, bu kod çalışıyor ama kaynak dosya 7MB ve bu bana sadece 52KB indir, ne yanlış olabilir? URL, webserver.tld / folder / download /…
Muflix

@Simon East, lütfen bana yardım edebilir misin stackoverflow.com/questions/30861112/…
Nathan Srivi

Bu komut dosyası ile bir zaman aşımı hatası beklediğiniz belirtilmelidir
kmoney12 5

30

Kodunuz zaman aşımını 1000 saniyeye ayarlar . Milisaniye için kullanın CURLOPT_TIMEOUT_MS.


13

Dosyayla aranızdaki zaman aşımlarından emin olmanız gerekir. Bu durumda PHP ve Curl.

Bir aktarım hala etkinken Curl'a hiçbir zaman zaman aşımını bildirmemek CURLOPT_TIMEOUTiçin 0, yerine ayarlamanız gerekir 1000.

curl_setopt($ch, CURLOPT_TIMEOUT, 0);

PHP'de, yine zaman sınırlarını kaldırmalısınız veya kendi kendine PHP (varsayılan olarak 30 saniye sonra), Curl'un isteği boyunca komut dosyasını öldürür. Bu tek başına sorununuzu çözmelidir .
Ayrıca, veri bütünlüğüne ihtiyacınız varsa, aşağıdakileri kullanarak bir güvenlik katmanı ekleyebilirsiniz ignore_user_abort:

# 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);

İstemci bağlantısının kesilmesi, komut dosyasının yürütülmesini ve muhtemelen zarar veren verileri
ör. geçici olmayan veritabanı sorgusu, bir yapılandırma dosyası oluşturma, ecc.

Bu eski soruyu cevaplıyor çünkü bu konu motor aramalarında en üstte CURL_TIMEOUT.


8

İsteği bir tarayıcıdan çalıştıramazsınız, CURL isteğini çalıştıran sunucunun yanıt vermesini beklemek zaman aşımına uğrar. Tarayıcı muhtemelen varsayılan ağ zaman aşımı olan 1-2 dakika içinde zaman aşımına uğruyor.

Komut satırından / terminalden çalıştırmanız gerekir.


2
+1 - zaman aşımı büyük olasılıkla kıvrılma dışındadır. Bir şeyin periyodik olarak çıktısını aldığınızdan emin olarak tarayıcı zaman aşımı etrafında çalışabilirsiniz; tarayıcılar genellikle daha fazla veri aldıklarında zaman aşımlarını sıfırlar. Ama bu bir hack; CLI üzerinden çalıştırmak (neredeyse?) her zaman tercih edilir.
Frank Farmer

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.