Встановлення тайм-ауту Curl у PHP


230

Я запускаю запит на згортання в базі даних eXist через php. Набір даних дуже великий, і як результат, базі даних послідовно потрібно довгий час, щоб повернути відповідь XML. Щоб виправити це, ми створили запит на згортання, з тим, що, як очікується, буде тривалим часом.

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

Однак запит на згортання послідовно закінчується до завершення запиту (<1000 при запиті через браузер). Хтось знає, чи це правильний спосіб встановити тайм-аути в очікуванні?

Відповіді:


346

Дивіться документацію: http://www.php.net/manual/en/function.curl-setopt.php

CURLOPT_CONNECTTIMEOUT- кількість секунд, які потрібно чекати, намагаючись підключитися. Використовуйте 0, щоб чекати нескінченно.
CURLOPT_TIMEOUT- Максимальна кількість секунд, щоб дозволити виконання функцій CURL.

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

також не забудьте збільшити час самостійного виконання php скрипту:

set_time_limit(0);// to infinity for example

13
Вам не потрібно, set_time_limit(0);якщо сценарій працює на консолі.
CONvid19

6
@PedroLobito, що ви згадуєте, це конфігурація php на cli за замовчуванням, але можливо, що це, можливо, було змінено.
cherouvim

4
@cherouvim, очевидно, правильно тут (просто біжіть php -d max_execution_time=1 -r 'while(true){$r=1*1;}'чи щось спостерігайте в дії, що в кліпі немає магічного прапора «завжди необмежено».
Wrikken

@ Pedro Lobito вам не потрібен, set_time_limit(0)якщо ви не використовуєте його всередині циклу.
Віктор Джорас

58

Гм, мені здається, CURLOPT_TIMEOUTвизначає кількість часу, яке може виконувати будь-яка функція CURL для виконання. Я думаю, що ви насправді повинні дивитись на це CURLOPT_CONNECTTIMEOUT, оскільки це говорить про CURL максимальну кількість часу, щоб зачекати, коли з'єднання завершиться.


Хоча документи в PHP говорять CURLOPT_TIMEOUTпро те, скільки часу займає функція, основні документи бібліотеки завитків, здається, говорять про те, скільки часу займає запит, що цікаво відрізняти - не впевнений, який спосіб це прочитати!
fideloper

Я думаю , що тут найкраща інтерпретація: stackoverflow.com/questions/27776129 / ...
fideloper

33

З цим є химерність, яка може бути актуальною для деяких людей ... Із коментарів документів PHP.

Якщо ви хочете, щоб CURL таймаутував менше ніж за одну секунду, ви можете використовувати CURLOPT_TIMEOUT_MS, хоча в "Unix-подібних системах" є помилка / "функція", яка спричиняє негайний час очікування libcurl, якщо значення <1000 мс з помилкою "cURL Помилка (28). Час очікування досягнуто ". Пояснення такої поведінки:

"Якщо libcurl побудований для використання стандартного розв'язувача імен системи, ця частина передачі все одно використовуватиме роздільну здатність на повну секунду для таймаутів, з мінімальним дозволом часу в секунду."

Що це означає для розробників PHP, це "Ви не можете скористатися цією функцією, не спробувавши її спочатку, тому що ви не можете сказати, чи використовує libcurl стандартний роздільник імен системи (але ви можете бути впевнені, що це так)"

Проблема полягає в тому, що на (Li | U) nix, коли libcurl використовує стандартний розв’язувач імен, під час дозволу імені піднімається SIGALRM, який, на думку libcurl, є сигналом очікування.

Рішення полягає у відключенні сигналів за допомогою CURLOPT_NOSIGNAL. Ось приклад сценарію, який запитує себе, викликаючи затримку на 10 секунд, щоб ви могли перевірити тайм-аути:

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

Від http://www.php.net/manual/en/function.curl-setopt.php#104597


Привіт, цей код працює, але вихідний файл становить 7 Мб, і це завантаження мені лише 52 КБ, що може бути не так? URL - це щось на зразок webserver.tld / папка / скачати /…
Muflix

@Simon Схід може ви допомогти мені stackoverflow.com/questions/30861112 / ...
Натан Srivi

Слід зазначити, що ви очікуєте помилки тайм-
аута

30

Ваш код встановлює час очікування на 1000 секунд . Протягом мілісекунд використовуйте CURLOPT_TIMEOUT_MS.


13

Вам потрібно буде переконатися в проміжках часу між вами та файлом. У цьому випадку PHP та Curl.

Щоб сказати Curl ніколи не очікувати, коли передача все ще активна, потрібно встановити CURLOPT_TIMEOUTїї 0замість 1000.

curl_setopt($ch, CURLOPT_TIMEOUT, 0);

Знову ж таки, у PHP ви повинні зняти обмеження часу, або PHP самостійно (через 30 секунд за замовчуванням) знищить сценарій за запитом Curl. Це лише має вирішити вашу проблему .
Крім того, якщо вам потрібна цілісність даних, ви можете додати рівень захисту, використовуючи 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);

Відключення клієнта перерве виконання сценарію та, можливо, пошкодить дані,
наприклад. неперехідний запит до бази даних, створення конфігураційного файлу, ек.

Відповідаючи на це старе питання, оскільки ця тема знаходиться вгорі під час пошуку двигуна CURL_TIMEOUT.


8

Ви не можете запустити запит у веб-переглядачі, він очікує на очікування часу, коли сервер, на який працює запит CURL, відповість. Можливо, веб-переглядач закінчується через 1-2 хвилини, мережевий час очікування за замовчуванням.

Запустити його потрібно з командного рядка / терміналу.


2
+1 - тайм-аут, ймовірно, зовнішній для завивання. Ви можете реально подолати час очікування браузера, переконуючись періодично виводити щось; Зазвичай браузери скидають час очікування щоразу, коли отримують більше даних. Але це хак; біг через CLI (майже?) завжди кращий.
Френк Фермер

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.