multi curl - теряются потоки

Bars

Новичок
Взгляните на 63-ю строчку, там производится INSERT результата cURL в базу данных. Но почему-то при одинаковом количестве результатов (потоков), инсертится в базу всегда почему-то разное количество, то есть какие-то потоки теряются и INSERT внутри них не происходит

PHP:
<?
        $mhs = array();
        $keywords = array('0' => 'movers', '1' => 'moving companies');
        $locs = array('0' => 'Los Angeles, CA', '1' => 'Los Angeles County, CA');
        foreach ($keywords as $key_id => $key) {
            $mhs[$key_id] = curl_multi_init();
            foreach ($locs as $loc_id => $loc_name) {
                $chm = curl_init();
                curl_setopt($chm, CURLOPT_URL, 'http://url.ru');
                curl_setopt($chm, CURLOPT_SSL_VERIFYHOST, FALSE);
                curl_setopt($chm, CURLOPT_SSL_VERIFYPEER, FALSE);
                curl_setopt($chm, CURLOPT_FOLLOWLOCATION, TRUE);
                curl_setopt($chm, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($chm, CURLOPT_HEADER, FALSE);
                curl_setopt($chm, CURLOPT_USERAGENT, $useragents[rand(0, $uaCount-1)]);
                curl_setopt($chm, CURLOPT_TIMEOUT, 12);
                curl_multi_add_handle($mhs[$key_id], $chm);
            }

            $running = null;
            while (($mrc = curl_multi_exec($mhs[$key_id], $running)) == CURLM_CALL_MULTI_PERFORM);
            while ($running && $mrc == CURLM_OK) {
                if ($running and curl_multi_select($mhs[$key_id]) != - 1) {
                    do {
                        $mrc = curl_multi_exec($mhs[$key_id], $running);
                        // Если поток завершился
                        if ($info = curl_multi_info_read($mhs[$key_id]) and $info['msg'] == CURLMSG_DONE) {
                            $ch1 = $info['handle'];
                            if ($info['result'] > 0) {
                                // Произошла ошибка
                            } else {
                                // Ответ получен
                                $data = curl_multi_getcontent($info['handle']).'';
                                $data = str_get_html($data);
                                $h1 = $data->find('h1');
                                if (strlen($data) > 10 || count($h1) > 0) {
                                    // То что должно произойти, но происходит не всегда
                                    $stmt2 = $db->prepare("INSERT INTO $table (`pid`, `key`, `loc`, `day`, `pos`, `dif`) VALUES (:pid, :key, :loc, $cday, :pos, :dif)");
                                    // ...
                                }
                            }

                            curl_multi_remove_handle($mhs[$key_id], $ch1);
                            curl_close($ch1);
                            unset($ch1);
                        }
                    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
                }

                usleep(100);
            }

            //curl_multi_close($mhs[$key_id]);
        }

        foreach ($mhs as $keey => $value) curl_multi_close($mhs[$keey]);
?>
 
Последнее редактирование:

Bars

Новичок
Это очень важно, надо сдать сегодня рабочий проект. Нельзя терять ни потока
 

AmdY

Пью пиво
Команда форума
Ну, это ты должен дебажить. посмотри логи, добавь отладочной информации. Мы по обрывкам кода угадать врят ли можем.
 

antson

Новичок
Партнер клуба
$proxies[rand(0, $proxiesCount-1)]) - многопоточный грабер через прокси ;(
здесь не обсуждают граберы . а также обходы банов и 100% аптайм проксей.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
А если серьезно - у тебя нет обработки ошибок. Далеко не каждое соединение завершается успешно, это тоже надо обрабатывать. К тому же, у разных соединений разные таймауты.

Вообще Курл малти надо готовить немного иначе. Я как-то делал доклад на эту тему на devconf.

Бери мои примеры вот и вот, и копай.
 
  • Like
Реакции: Bars

Bars

Новичок
Оказывается у меня несколько ошибок, еле еле их отыскал.
1. Я использовал TIMEOUT вместо CONNECTTIMEOUT
2. Я чекал на ошибки только 2 из 3 соединений, но первое соединение никак не дебажилось, поэтому я и подумать не мог, что там можно сделать проверку. Короче очень запутанный пункт, чтобы его описывать, но решить я его решил
3. Даже устранив ошибку №1, 0-3 потока терялись. Поэтому убрал CONNECTTIMEOUT и потери пропали, а так как он все равно существует (и равен 300 сек), я его оставил, но в 60 сек вместо 12-ти предыдущих

UPD: Пришлось потратить еще время сна, потому что потери до сих пор остались. Много переписал
 
Последнее редактирование:

antson

Новичок
Партнер клуба
@Bars, чтобы не терять надо сперва на генерировать нужные таски , а потом проверять их исполнение.
т.е. сперва проинсертить записи со статусом ожидание.
когда начинаешь запрос меняешь статус на впроцессе и сохраняешь время запроса
по успешному/неуспешному окончанию заносишь данные в запрос и статус исполнен/ошибка, плюс что там для протоколирования , отладки нуно.
по крону проверяешь зомбей, пытаешься исправить ошибки, если вожможно автоматом.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Не надо использовать базу для логов, runtime-статусов, сессий, как хранилище файлов и медиа. Исключения есть, но они имеют смысл в очень-очень редких случаях.
Для этих целей есть другие инструменты - редис, файловые системы, сислог, pinba.

Базу надо использовать для постоянного хранения связанных данных бизнес-логики, по которым будут выполняться реляционные sql-запросы.
 
Сверху