php curl_multi_thread не работает должным образом - PullRequest
0 голосов
/ 14 ноября 2018

Это код, который я использую

function initiate_curl($row, $mh) {
    $ch = curl_init();
    $url = 'http://openapi.gbis.go.kr/ws/rest/busarrivalservice'; /*URL*/
    $queryParams = '?' . urlencode('serviceKey') . "SERVICE API KEY"; /*Service Key*/
    $queryParams .= '&' . urlencode('stationId') . '=' . urlencode($row['stId']); /**/
    $queryParams .= '&' . urlencode('routeId') . '=' . urlencode($row['busRouteId']); /*노선ID*/
    $queryParams .= '&' . urlencode('staOrder') . '=' . urlencode($row['seq']);

    curl_setopt($ch, CURLOPT_URL, $url . $queryParams);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

    curl_multi_add_handle($mh, $ch);
    return $ch;

}

$mh = curl_multi_init();
$arr = array();
$rows = array();

while ($row = mysqli_fetch_array($query)) {
    array_push($arr, initiate_curl($row, $mh));
    array_push($rows, $row);
}
$running = null;
do {
  curl_multi_exec($mh, $running);
} while ($running);

foreach($arr as $curl) {curl_multi_remove_handle($mh, $curl);}
curl_multi_close($mh);
foreach($arr as $key=>$curl) {
    **DO MY WORK
}

В большинстве случаев это работает нормально, но иногда я получаю значение NULL в результате запроса. Тем не менее, когда я иду к API через ввод URL-адреса, он прекрасно возвращает значение. Кроме того, объект, который возвращается как нулевой, изменяется в любое время, поэтому я на 100% уверен, что это ошибка моей части curl_multi.

Я неправильно это реализую или просто не так надежно в использовании?

1 Ответ

0 голосов
/ 14 ноября 2018

(это не ответ, но слишком много, чтобы публиковать его в качестве комментариев)

Во-первых, это дерьмовый способ написать строку запроса в кодировке URL в PHP:

$queryParams = '?' . urlencode('serviceKey') . "SERVICE API KEY"; /*Service Key*/
$queryParams .= '&' . urlencode('stationId') . '=' . urlencode($row['stId']); /**/
$queryParams .= '&' . urlencode('routeId') . '=' . urlencode($row['busRouteId']); /*노선ID*/
$queryParams .= '&' . urlencode('staOrder') . '=' . urlencode($row['seq']);

PHP имеет функцию, специально предназначенную для написания URL-кодированных строк запроса, которая называется http_build_query, и код будет выглядеть намного лучше, если он будет написан так:

$queryParams = http_build_query(array(
    'serviceKey' => 'SERVICE API KEY',
    'stationId' => $row['stId'],
    'routeId' => $row['busRouteId'],
    'staOrder' => $row['seq']
));

, curl_multi_exec - это асинхронная функция,он вернется, как только curl ожидает io, то есть вызов curl_multi_exec до тех пор, пока $ running не станет ложным, будет использовать 100% ЦП (из 1 ядра ЦП), что совершенно не нужно, и некоторые провайдеры shared-webhost могут даже убить ваш скрипт дляиспользуя слишком много процессора .. используйте curl_multi_select для сна, пока curl_multi_exec не будет чем-то заниматься (что снизит загрузку ЦП до 1-2% вместо 100%), попробуйте следующее:

$running = null;
for(;;){
  curl_multi_exec($mh, $running);
  if(!$running){
     break;
  }
  curl_multi_select($mh);
}

иногда я получаю нулевое значение в результате запроса

о каком запросе вы говорите?Вы имеете в виду, что вы получаете NULL из запроса MySQL?например, что mysqli_fetch_array иногда возвращает NULL?в этом случае вам нужно проверить реализацию mysqli_fetch_array, это не стандартная функция PHP, это код userland-php.(однако, с таким же именем mysqli_result::fetch_array - это обычная базовая функция PHP, и когда эта функция возвращает NULL, это означает, что вы уже получили последний результат - или, если она возвращает NULL при первом выполнении, это означает, что было 0 результатов.всего)

...