Многопоточность курл миф или реальность?

Тема в разделе "PHP", создана пользователем Levitt, 10 дек 2012.

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

    Levitt

    Регистр.:
    20 май 2008
    Сообщения:
    356
    Симпатии:
    34
    Многомпоточность с помощью курл реально или нет?

    Т.е. возможно ли вообще параллельное получение данных с сайтов в одном исполняемом скрипте и ест ли какой-то прирост в скорости исполнения?
     
  2. SolutionFix

    SolutionFix 17 лет програмлю ;)

    Регистр.:
    20 ноя 2006
    Сообщения:
    272
    Симпатии:
    318
    Во-первых параллельное выполнение PHP кода довольно несложно достигается с помощью распределения по процессам (запуск скриптом самого себя через апач, системный fork, браузер клиента, cron и так далее), и уж явно это одни из базовых возможностей и их никогда не прикроют - но это не относится к вопросу ТС.

    А ответ будет таким: Да, возможно, например вот код - получение содержимого сайтов, параметр $data - список элементов, может быть просто списком адресов URL, или иметь поле 'url', 'post' и так далее (например для постинга).
    Тут два замечания:
    1) Такой код будет параллельно получать данные с разных сайтов, но не является многопоточным в точном смысле этого слова. Здесь библиотека curl использует неблокирующие сокеты и системные вызовы select/poll.
    2) Из-за известного бага в библиотеке curl, такой код не будет работать с socks проксями, только напрямую или с http-проксями.

    PHP:
    function multiRequest($data$Timeout$options = array())  {
        
    $curly = array();
        
    $result = array();
        
    $mh curl_multi_init();
     
        foreach (
    $data as $id => $d)
        {
            
    $curly[$id] = curl_init();
            
    $url = (is_array($d) && !empty($d['url'])) ? $d['url'] : $d;
            
    curl_setopt($curly[$id], CURLOPT_URL,            $url);
            
    curl_setopt($curly[$id], CURLOPT_HEADER,        0);
            
    curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER1);
            
    curl_setopt($curly[$id], CURLOPT_FOLLOWLOCATION1);
            
    curl_setopt($curly[$id], CURLOPT_USERAGENT'Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)');
            if (
    is_array($d))
                if (!empty(
    $d['post']))
                {
                    
    curl_setopt($curly[$id], CURLOPT_POST,      1);
                    
    curl_setopt($curly[$id], CURLOPT_POSTFIELDS$d['post']);
                }
            if (!empty(
    $options)) curl_setopt_array($curly[$id], $options);
            
    curl_multi_add_handle($mh$curly[$id]);
        }
        
    $running null;
        
    $Start microtime(true);
        do {
            
    usleep(100000);
            
    $mrc curl_multi_exec($mh$running);
            
    usleep(100000);
        } while(
    $running and (microtime(true) - $Start $Timeout));
     
        foreach(
    $curly as $id => $c)
        {
            
    $result[$id] = curl_multi_getcontent($c);
            
    curl_multi_remove_handle($mh$c);
        }
        
    curl_multi_close($mh);
        return 
    $result;
    }

    "ест ли какой-то прирост в скорости исполнения" - ест, ест :)
    ну фактически данная функция уменьшит время получения данных с суммы всех времен элементов (при работе в один поток) до времени получения самого медленного элемента в списке. Естественно если хватит канала.

    PS У меня уже лет 8 крутится скрипт - прокси чекер именно используя подобную функцию, в пакете по 300-500 запросов.
     
    Ultharas, Sankaboy, akifjev и 2 другим нравится это.
  3. KillDead

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    883
    Симпатии:
    540
    слышал подобное раньше, но в последнее время когда загружал носки - всё хорошо было. Какие именно носки не работают с курлом?

    очень значительный, особенно если с проксями.


    да, лучше делать очередь и постоянно добавлять новые урлы в процессе, правда есть беда с <5.3 пхп- сервер может умереть их за бага в курл_селект. Но это обходится довольно изящно - создаются не курлы, а мультикурлы, которые можно опросить вручную.

    o_O Хм, а качество результата- хорошее? Ибо я пытался сделать прокси чекер- ооочень долго парсит, несравнимо с соксами, да и половина вроде бы рабочих- сразу подыхает. + носки как я понимаю не чекаешь? У меня курл за носки принимал половину обычных, даж не анонимных проксей
     
  4. gothmog

    gothmog Постоялец

    Регистр.:
    18 июн 2011
    Сообщения:
    60
    Симпатии:
    24
    Сам по себе курл может запускаться в многопоточном режиме и как угодно. Проблема тут скорее в РНР, который не поддерживает потоки, т.к. изначально создавался для разработки сайтов, а не спамсофта. Вроде как нужно использовать multi_curl, который открывает несколько хендлов курла одновременно и запускает их.
     
  5. alar

    alar Писатель

    Регистр.:
    11 янв 2013
    Сообщения:
    1
    Симпатии:
    0
    это скорее не совсем многопоточность
    multi_curl просто открывает новые хендлы одновременно (как сказал gothmog) - не дожидаясь закрытия предыдущего
     
  6. vasyap

    vasyap Писатель

    Регистр.:
    20 июл 2012
    Сообщения:
    1
    Симпатии:
    0
    а что за баг с носками? никогда его не встречал.

    и, кстати, php'шный multi_curl можно немного пропатчить для совершенно феноменальных результатов %)
     
    Последнее редактирование модератором: 25 сен 2014
  7. svfolder

    svfolder Постоялец

    Регистр.:
    31 июл 2013
    Сообщения:
    95
    Симпатии:
    39
    selkin.shura нравится это.
  8. x_Lex

    x_Lex Создатель

    Заблокирован
    Регистр.:
    3 июн 2006
    Сообщения:
    32
    Симпатии:
    33