Curl и http/2 multiplex, или как я хотел пустить несколько запросов в 1 соединение

Тема в разделе "PHP", создана пользователем babahalki, 3 дек 2017.

Модераторы: latteo
  1. babahalki

    babahalki

    Регистр.:
    6 май 2016
    Сообщения:
    246
    Симпатии:
    98
    Привет.
    Делаю либу для работы с удаленными файлами, а поскольку я сижу через очень долгий канал, каждое соединение добавляет по 150-200мс в итоге тестируя свою первую функцию filesize_remote() меня неприятно удивила задержка в 300мс, сначала 150мс первое соединение, а потом на еще 1 редирект 150мс. А я всего лишь увидел размер файла. Решил попробовать использовать http/2, сам протокол мне запустить удалось, но вот заставить curl использовать 1 соединение никак не получается.

    Код:
    <?php
        function callbackheader($ch, $hdr) { 
    
            //делим строку по двоеточию на 2 эл. максимум
            $v = explode(':', $hdr, 2);
            if(count($v) < 2){
                //если двоеточия не было, тогда оставим старый ключ и значение
                $key = 0;
                   $val = explode(' ', trim($v[0]));
            }else{
                $key = strtolower($v[0]);
                $val = trim($v[1]);
            }
            $header[$key] = $val;
             print_r($header);
            return strlen($hdr); 
        } 
    
        function callbackdata($ch, $data) { 
            print $data;
            return strlen($data); 
        } 
    
            $src = 'https://www.xiaomi2buy.ru/files/products/12101.10x10.jpg';
            $ch = curl_init();
            $opt = array(
                CURLOPT_URL => $src, // устанавливаем URL
                CURLOPT_PIPEWAIT => 1, //1 to wait for pipelining/multiplexing
                CURLOPT_FOLLOWLOCATION => 1, //redirect to location header
                CURLOPT_MAXREDIRS => 10, //max redirects
                CURLOPT_HTTP_VERSION => 3, // пробуем использовать http/2
                CURLOPT_SSL_VERIFYHOST => 0, //отключаем проверку соответсвия имени на сертификате хосту
                CURLOPT_RETURNTRANSFER => 1, //вернуть результат через curl_exec($ch), а не на экран.
                CURLOPT_HEADERFUNCTION => 'callbackheader',
                CURLOPT_WRITEFUNCTION => 'callbackdata',
            );
            curl_setopt_array($ch, $opt);
           
            print '<PRE>';
            curl_exec($ch);
    
    
    Даже в таком примере происходит 2 соединения, судя по показаниям netstat -atc на сервере.

    А браузер нормально работает через 1 соединение, даже если вручную в адресной строке вводить разные адреса 1 хоста.

    Кому удавался трюк?
     
  2. latteo

    latteo Эффективное использование PHP, MySQL

    Moderator
    Регистр.:
    28 фев 2008
    Сообщения:
    1.611
    Симпатии:
    1.539
    Проверь версию курла и php
    Но это мало чем поможет, потому как HTTP2 нужен для выполнения параллельных запросов к одному домену
    У тебя происходит редирект твоего запроса с www. на domain и это 2 разных домена.

    curl даже гораздо более ранних версий по умолчанию переиспользует соединение, и единственное, что для этого надо, это не создавать заново сеанс через curl_init();
    Вот таким вот образом:
    PHP:
            $src 'https://www.xiaomi2buy.ru/files/products/12101.10x10.jpg';
            
    $ch curl_init();
            
    $opt = array(
                
    CURLOPT_URL => $src// устанавливаем URL
                
    CURLOPT_FOLLOWLOCATION => 0//redirect to location header
                
    CURLOPT_SSL_VERIFYHOST => 0//отключаем проверку соответсвия имени на сертификате хосту
                
    CURLOPT_RETURNTRANSFER => 1//вернуть результат через curl_exec($ch), а не на экран.

            
    );
            
    curl_setopt_array($ch$opt);
            
    curl_exec($ch);

            
    $src 'https://www.xiaomi2buy.ru/';

            
    curl_setopt($chCURLOPT_URL$src);
            
    curl_exec($ch);
    курл получает 2 странички через одно соединение.

    В твоём случае, проще будет убрать www
    PHP:
    $src 'https://xiaomi2buy.ru/files/products/12101.10x10.jpg';
     
  3. babahalki

    babahalki

    Регистр.:
    6 май 2016
    Сообщения:
    246
    Симпатии:
    98
    Спасибо.

    Версии у меня вот:
    curl 7.54.1
    php 7.1.7

    У меня пример специально упрощен, в реальности там все сложнее закручено. Это просто тренировка на кошках.

    Действительно, если хост на 100% совпадает, то вроде как в 1 соединение все пускается. Выходит при редиректе, поскольку хост становится другим мне никак не избежать 2 соединений.