curl_multi를 이용한 병렬처리
첨부화일은 REST용 병렬처리 샘플 소스이다.
(http://gonzalo123.com/2010/02/06/building-a-rest-client-with-asynchronous-calls-using-php-and-curl/)
PHP에서 시간 많이 걸리는 처리를 병렬로 실행하여 고속화 할수 있다.
PHP에는 pcntl_fork라는 프로세스를 포크할수 있는 함수가 있지만 CGI모드에서만 유효해
일반적으로 PHP를 Apache모듈로 동작시키는 환경에서는 사용할수 없다.
그외에는 system함수등을 사용하여 시스템콜로 백그라운드에서 처리시키는 경우이다.
-
system('php -f test.php > /dev/null &');
curl_multi를 사용해서 병렬처리
PHP5에서 curl_multi_*라는 함수군을 사용할수 있게 되었다.
curl함수는 대상을 실행시켜(URL등으로) 출력되는 결과를 리다이렉트등의 페이지 이동없이 얻을수 있다.
PHP5에서는 이러한 처리는 병렬로 가능하게 하는 curl_multi시리즈가 추가 되었다.
이것을 이용해 API에 동시에 복수의 리퀘스트를 던져 병렬처리가 되도록 해보자
-
<?php
-
header('Content-type:text/html; charset=UTF-8');
-
-
//동시 처리시킬 URL
-
$url_list = array(
-
);
-
-
$time = time();
-
-
//실행
-
$res = fetch_multi_url($url_list);
-
-
//결과 출력
-
echo '실행 결과:<pre>';
-
print_r($res);
-
echo '</pre>';
-
-
//실행 시간
-
echo '--<br />time:'.(time() - $time).' sec';
-
-
/**
-
* fetch_multi_url
-
*
-
* @param array $url_list
-
* @param int $timeout
-
* @return array
-
*/
-
function fetch_multi_url( array $url_list, $timeout=0 ) {
-
$mh = curl_multi_init();
-
-
foreach ($url_list as $i => $url) {
-
$conn[$i] = curl_init($url);
-
curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);
-
curl_setopt($conn[$i],CURLOPT_FAILONERROR,1);
-
curl_setopt($conn[$i],CURLOPT_FOLLOWLOCATION,1);
-
curl_setopt($conn[$i],CURLOPT_MAXREDIRS,3);
-
-
//SSL증명서 무시
-
curl_setopt($conn[$i],CURLOPT_SSL_VERIFYPEER,false);
-
curl_setopt($conn[$i],CURLOPT_SSL_VERIFYHOST,false);
-
-
//타임아웃
-
if ($timeout){
-
curl_setopt($conn[$i],CURLOPT_TIMEOUT,$timeout);
-
}
-
-
curl_multi_add_handle($mh,$conn[$i]);
-
}
-
-
$active = null;
-
do {
-
$mrc = curl_multi_exec($mh,$active);
-
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
-
-
while ($active and $mrc == CURLM_OK) {
-
if (curl_multi_select($mh) != -1) {
-
do {
-
$mrc = curl_multi_exec($mh,$active);
-
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
-
}
-
}
-
-
if ($mrc != CURLM_OK) {
-
echo '읽기 에러가 발생:'.$mrc;
-
}
-
-
//결과 취득
-
$res = array();
-
foreach ($url_list as $i => $url) {
-
if (($err = curl_error($conn[$i])) == '') {
-
$res[$i] = curl_multi_getcontent($conn[$i]);
-
} else {
-
echo '취득실패:'.$url_list[$i].'<br />';
-
}
-
curl_multi_remove_handle($mh,$conn[$i]);
-
curl_close($conn[$i]);
-
}
-
curl_multi_close($mh);
-
-
return $res;
-
}
-
<?php
-
sleep(5);
-
echo 'pid='.$_GET['pid'];
개당 5초간 sleep
이 sleep.php를 4번 실행한다면
5초 x 4회 = 20초정도 걸릴것이다.
-
Array
-
(
-
[0] => pid=1
-
[1] => pid=2
-
[2] => pid=3
-
[3] => pid=4
-
)
-
-
--
-
time:5 sec
5초만에 실행되었다.
DNS해석처리를 병렬로 실행
실제의 IP어드레스를 호스트명으로 바꾸는 처리를 병렬로 해보았다.
중복하지 않는 IP1,000개에 대하여 php의 gethostbyaddr함수를 실행
결과
-----------------------------------
순차:124초
병력(10개):33초
-----------------------------------
시간이 많이 걸리는 때는 set_time_limit의 설정을..
ignore_user_abort를 사용하면 백그라운드 처리도 가능하다.