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

Levitt

Профессор
Регистрация
20 Май 2008
Сообщения
361
Реакции
43
Многомпоточность с помощью курл реально или нет?

Т.е. возможно ли вообще параллельное получение данных с сайтов в одном исполняемом скрипте и ест ли какой-то прирост в скорости исполнения?
 
Во-первых параллельное выполнение 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_RETURNTRANSFER, 1);
        curl_setopt($curly[$id], CURLOPT_FOLLOWLOCATION, 1);
        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 запросов.
 
2) Из-за известного бага в библиотеке curl, такой код не будет работать с socks проксями, только напрямую или с http-проксями.
слышал подобное раньше, но в последнее время когда загружал носки - всё хорошо было. Какие именно носки не работают с курлом?

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


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

PS У меня уже лет 8 крутится скрипт - прокси чекер именно используя подобную функцию,
o_O Хм, а качество результата- хорошее? Ибо я пытался сделать прокси чекер- ооочень долго парсит, несравнимо с соксами, да и половина вроде бы рабочих- сразу подыхает. + носки как я понимаю не чекаешь? У меня курл за носки принимал половину обычных, даж не анонимных проксей
 
Сам по себе курл может запускаться в многопоточном режиме и как угодно. Проблема тут скорее в РНР, который не поддерживает потоки, т.к. изначально создавался для разработки сайтов, а не спамсофта. Вроде как нужно использовать multi_curl, который открывает несколько хендлов курла одновременно и запускает их.
 
это скорее не совсем многопоточность
multi_curl просто открывает новые хендлы одновременно (как сказал gothmog) - не дожидаясь закрытия предыдущего
 
а что за баг с носками? никогда его не встречал.

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