php curl_multi_thread not working properly

106 Views Asked by At

This is the code I am using

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
}

Most of the times it works fine but sometimes I get null as a result of the query. However, when I go to the API through typing the url, it returns the value perfectly. Also, the object that is returned as null changes any time so I'm 100% sure that this is the fault of my curl_multi part.

Am I implementing this wrong or is it simply not that reliable to use?

1

There are 1 best solutions below

1
On

(this is not an answer, but too much to be posted as comments)

first off, this is a shitty way to write a URL-encoded query string in 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 has a function specifically dedicated to writing URL-encoded query strings, called http_build_query, and the code would look much better if written as:

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

also, curl_multi_exec is an async function, it will return as soon as curl is waiting for io, meaning that calling curl_multi_exec until $running becomes false will use 100% cpu (of 1 cpu core), which is completely unnecessary, and some shared-webhost providers may even kill your script for using too much cpu .. use curl_multi_select to sleep until curl_multi_exec has something to do (which will turn the CPU usage down to 1-2% instead of 100%), try this:

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

sometimes I get null as a result of the query

what query are you talking about? do you mean you get NULL from the mysql query? eg that mysqli_fetch_array sometimes return NULL? in which case you need to check out the implementation of mysqli_fetch_array, it's not a standard PHP function, it's userland-php code. (however, the similarly named mysqli_result::fetch_array is a normal core PHP function, and when that function returns NULL, it means you've already fetched the last result - or if it returns NULL on the first execution, it means there was 0 results in total)