Так обычно и бывает – стоит только реализовать какой-либо сервис на сайте, тут же и конкуренты сделают тоже самое, и, как правило – ещё и лучше. Так получилось и у меня. Прицепил поисковый сервис на сайт турагентства своей жены. И этот сервис для целей авторизации на серверах провайдера этого сервиса использует прокси – скрипты, использующие file_get_contents на стороне нашего сервера для загрузки поисковых форм и результатов поиска с серверов провайдера. После реализации я не обратил внимания на существенные задержки (до 5 секунд), у конкурентов такого сервиса вообще не было. Но вот – появился. И без задержек. Что же, разберёмся с причинами задержек в моём случае и устраним их.

Времени на поиски убил много. Приведу кусок кода для тестирования:

error_reporting(0);
ini_set('default_socket_timeout', 29);

$url = $base_url.$type."?".$_SERVER['QUERY_STRING'];
$context = stream_context_create(
    array(
        'http' => array(
            'method' =>    "GET", 
            'header' =>    array (
                "Accept-language: ru",
                "Connection: close",
                "Content-Type: text/html; charset=utf-8"
            )
        )
    )
);
$page = file_get_contents($url, false, $context);
if(!($page === false) && strlen($page) > 0) {
    echo $page;            
} else {
    echo "В настоящее время сервис недоступен";
}        

Можно обойтись и без создания контекста, результат будет тот же – на file_get_contents возникает задержка (порядка 5 секунд). Свои приключения описывать не буду, опишу лишь результат.

Причина оказалось банальной. Мой web сервер построен на базе Windows 2008 R2 Web Server, IIS7 + PHP 5.3.  Сервер находится в локальной сети за ISA Server. Установлен FWC. И для internet explorer указан прокси сервер (на ISA хосте).

Выяснилось следующее: PHP на IIS7 при внешних запросах использует параметры подключения IE, то есть в моём случае – подключение через прокси сервер. Стоило мне отключить прокси для web сервера с PHP, предварительно дорисовав необходимые разрешающие правила на ISA – и задержки исчезли!

Есть варианты “отключения” прокси непосредственно в php сценарии, но это решение мне не кажется целесообразным. Так что – отключайте прокси в IE  для сервера IIS7+PHP.

Отзывы » (8)

  1. Как выяснил сейчас, проблема не только в file_get_contents. Проблема ещё и в резком падении производительности echo при большом объёме (больше 10 Кб) информации.
    Пришлось лечить следующим костылём (время выдачи страницы сократилось с 10 секунд до долей секунды):

    //	echo $page;
    	for ($i=0; $i <= strlen($page) / 1024; $i++) {
    	    echo substr($page, $i*1024, 1024);
    	};
    

    Сейчас разбираюсь с причинами этого поведения, найду — опишу.

  2. Сегодня выяснил ещё один факт прелестный. Делаю запрос к прокси скрипту, который через file_get_contentsполучает и отдаёт через echoпорядка 15 Кб через прокси сервер — 10-15 секунд задержка. Отключаю прокси сервер — в районе 1 секунды. Будем искать дальше…

  3. Через echo microtime()опять заметил задержку в file_get_contents в 9 секунд. В результате заменил на следующий код:

    	$ch = curl_init();
    	curl_setopt($ch, CURLOPT_URL, $url);
    	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    	$page = curl_exec($ch);
    	curl_close($ch);
    

    Результат — 0.2 секунды. Хотя причину так и не нашёл.

  4. Нашёл таки закономерность. Только пока не могу её объяснить. В общем — система следующая.
    - имеем задержку, причём как на file_get_contents, так и на curl_exec, задержка в 9-10 секунд.
    - на том самом сервере, на котором крутится наш IIS7 + PHP, запускаем IE и открываем интересующий нас url (ну — тот самый, который мы пытаемся получить через file_get_contents)
    - и после этого задержка при выполнении php скрипта пропадает!

    При этом кеширование невиновно (ответ не кешируется, имеет динамически генерируемые данные). Так что же всё-таки может быть причиной такого поведения?

  5. Проблема по-прежнему была, как я понял, в прокси. Пришлось всё-таки в сценарии его явно прописать:

    	$ch = curl_init();
    	curl_setopt($ch, CURLOPT_URL, $url);
    	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    	curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 0);
    	curl_setopt($ch, CURLOPT_PROXY, 'proxy.inet.services.novgaro.ru:8080'); 
    	curl_setopt($ch, CURLOPT_PROXYUSERPWD, 'NOVGARO\sergey.s.betke:password');
    	$page = curl_exec($ch);
    	curl_close($ch);
    

    И задержки пропали.
    Вывод могу сделать пока только один. Сборка PHP под Windows использует настройки IE для определения необходимости использования прокси сервера. И если таковой прописан — идёт к нему. И проходит авторизацию при необходимости. А у меня через политику «спускается» флаг «автоматическое определение прокси-сервера». Как следствие — PAC и прочие прелести. Стоило явно задать прокси и авторизацию — задержки пропали.
    Осталось последнее «но»: эти параметры необходимо вынести в настройки сайта, на худой конец — в php.ini. Будем искать…
    И пока всё, что нашёл для установки параметров «по умолчанию»: stream-context-set-default.

  6. Антон:

    Вот спасибо добрый человек!Все четко и ясно. Столкнулся с той же проблемой практически

Опубликовать комментарий

XHTML: Вы можете использовать следующие HTML теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tags Связь с комментариями статьи:
RSS комментарии
Обратная ссылка