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

  • Автор темы Автор темы Bars
  • Дата начала Дата начала

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]);
?>
 
Последнее редактирование:
Это очень важно, надо сдать сегодня рабочий проект. Нельзя терять ни потока
 
Ну, это ты должен дебажить. посмотри логи, добавь отладочной информации. Мы по обрывкам кода угадать врят ли можем.
 
$proxies[rand(0, $proxiesCount-1)]) - многопоточный грабер через прокси ;(
здесь не обсуждают граберы . а также обходы банов и 100% аптайм проксей.
 
А если серьезно - у тебя нет обработки ошибок. Далеко не каждое соединение завершается успешно, это тоже надо обрабатывать. К тому же, у разных соединений разные таймауты.

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

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

UPD: Пришлось потратить еще время сна, потому что потери до сих пор остались. Много переписал
 
Последнее редактирование:
@Bars, чтобы не терять надо сперва на генерировать нужные таски , а потом проверять их исполнение.
т.е. сперва проинсертить записи со статусом ожидание.
когда начинаешь запрос меняешь статус на впроцессе и сохраняешь время запроса
по успешному/неуспешному окончанию заносишь данные в запрос и статус исполнен/ошибка, плюс что там для протоколирования , отладки нуно.
по крону проверяешь зомбей, пытаешься исправить ошибки, если вожможно автоматом.
 
Не надо использовать базу для логов, runtime-статусов, сессий, как хранилище файлов и медиа. Исключения есть, но они имеют смысл в очень-очень редких случаях.
Для этих целей есть другие инструменты - редис, файловые системы, сислог, pinba.

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