English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
【Доступ к HTTP】
Обычно мы используем множество методов для доступа к HTTP,主要包括: curl, socket, file_get_contents() и т.д.
Если сервер не отвечает в течение длительного времени, это может быть трагедией, так как легко можно убить весь сервер, поэтому при доступе к HTTP также необходимо учитывать проблему таймаутов.
[Доступ к HTTP через CURL]
CURL - это один из常用的 библиотек для доступа к интерфейсам протокола HTTP, которая имеет высокую производительность и некоторые функции поддержки параллельного выполнения.
CURL:
curl_setopt($ch, opt) может устанавливать некоторые настройки таймаутов, включая:
(Важно) CURLOPT_TIMEOUT - устанавливает максимальное время выполнения в секундах, которое позволяет cURL.
(Важно) CURLOPT_TIMEOUT_MS - устанавливает максимальное время выполнения в миллисекундах, которое позволяет cURL. (Добавлен в cURL 7.16.2. Доступен с PHP 5.2.3.)
CURLOPT_CONNECTTIMEOUT - время ожидания перед установлением соединения, если установлено в 0, то ожидание неограниченное время.
CURLOPT_CONNECTTIMEOUT_MS время ожидания при попытке подключения, в миллисекундах. Если установлено в 0, то ожидание бесконечно. Добавлено в cURL 7.16.2. С PHP 5.2.3 доступно.
CURLOPT_DNS_CACHE_TIMEOUT устанавливает время хранения информации DNS в памяти, по умолчанию 120 секунд.
Обычное время ожидания cURL:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60); //Достаточно установить количество секунд
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_USERAGENT, $defined_vars['HTTP_USER_AGENT']);
Использование обычного времени ожидания в секундах cURL:
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
Если cURL нужно использовать время ожидания в миллисекундах, нужно добавить:
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
Или:
curl_setopt ($ch, CURLOPT_NOSIGNAL, true); поддерживает настройку времени ожидания в миллисекундах
Пример запроса cURL с мillisecondовым временем ожидания:
<?php if (!isset($_GET['foo'])) { //Клиент $ch = curl_init('http://example.com/'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_NOSIGNAL, 1); //Внимание, время ожидания в миллисекундах должно быть установлено curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200); //Время ожидания в миллисекундах, добавлено в cURL 7.16.2. С PHP 5.2.3 можно использовать $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"; } echo "Received data: $data\n"; } } // Server sleep(10); echo "Done."; } ?>
Другие полезные советы:
1. По опыту можно сказать, что: версия cURL >= libcurl/7.21.0, мillisecondовое ожидание определенно сработает, запомните это.
2. Проблемы с мillisecondовым ожиданием в curl_multi... Поддержка мillisecondового ожидания для одного доступа, но при параллельных вызовах curl_multi не точна
[Доступ к HTTP через потоковую обработку]
Кроме curl, мы часто используем fsockopen или функции работы с файлами для обработки протокола HTTP, поэтому обработка времени ожидания в этой области также обязательна.
Обычно можно просто установить время ожидания подключения, но для обработки времени ожидания потока чтения необходимо отдельно обрабатывать.
Напишите свой код обработки:
$tmCurrent = gettimeofday(); $intUSGone = ($tmCurrent['sec'] - $tmStart['sec']) * 1000000 + ($tmCurrent['usec'] - $tmStart['usec']); if ($intUSGone > $this->_intReadTimeoutUS) { return false; }
или используйте встроенные функции обработки потоков stream_set_timeout() и stream_get_meta_data():
<?php // Timeout в секундах $timeout = 5; $fp = fsockopen("example.com", 80, $errno, $errstr, $timeout); if ($fp) { fwrite($fp, "GET / HTTP/1.0\r\n"); fwrite($fp, "Host: example.com\r\n"); fwrite($fp, "Connection: Close\r\n\r\n"); stream_set_blocking($fp, true); //Важное, установите режим не блокирующего выполнения stream_set_timeout($fp,$timeout); //Установить таймаут $info = stream_get_meta_data($fp); while ((!feof($fp)) && (!$info['timed_out'])) { $data .= fgets($fp, 4096); $info = stream_get_meta_data($fp); ob_flush; flush(); } if ($info['timed_out']) { echo "Connection Timed Out!"; } echo $data; } }
Таймаут file_get_contents:
<?php $timeout = array( 'http' => array( 'timeout' => 5 //Установить время ожидания, единицы измерения - секунды ) ); $ctx = stream_context_create($timeout); $text = file_get_contents("http://example.com/", 0, $ctx); ?>
Таймаут fopen:
<?php $timeout = array( 'http' => array( 'timeout' => 5 //Установить время ожидания, единицы измерения - секунды ) ); $ctx = stream_context_create($timeout); if ($fp = fopen("http://example.com/", "r", false, $ctx)) { while( $c = fread($fp, 8192)) { echo $c; } fclose($fp); } ?>
Вот и все, что я хотел рассказать вам о кратком рассмотрении методов решения проблемы таймаутов при обработке PHP и доступе к интерфейсу. Надеюсь, вам понравится и вы поддержите tuorial!