Mail함수등과 같은, 부하를 많이 주는 작업을 PHP에서 하게되면 클라이언트는 연결이 종료될때까지 마냥 기다리고 있어야 한다. 마찬가지로 만약 이 연결이 너무나 오래걸린다 싶으면 timeout이 걸려버려서 당황스럽게 만든다. 그렇다고 해서 set_time_limit만을 사용하면 그동안에 다른작업을 못하게 되므로 역시 문제가 된다. 물론 ajax를 통한 비동기적 통신이 이를 보완해줄 수 있겠지만 그래도 연결이 지속되기 때문에 시스템 효율상좋지 않을것으로 보인다.
제목에서 왜 백그라운드 작업과 멀티태스킹를 구분해 놓았냐면 백그라운드 작업은 실제 작업이 오래걸리는 알고리즘 상에 직접 적용하는 것을 의미하는것인 반면 멀티태스킹 부분은 오래걸리는 알고리즘을 외부에서 호출하는(->동시 작업에 있어서의 유용성을 얻기 위해) 부분에 대해 서술한 부분이기 떄문이다,
1. 백그라운드 작업 구현하기(알고리즘 상에서)
이를 위해서 구글링을 한 결과 다음과 같은 소스를 얻을 수 있었다. 원리라면 타겟 알고리즘이 실행되기 전에 임의로 헤더를 작성한 다음에 그냥 뿌려버려서 클라이언트에게 이미 컨넥션이 끝났다는것을 알려주어 클라이언트와의 연결을 끊지만, 사실 그 뒤에 자신 나름대로 일을 묵묵히 하는것이다. 단점이라면 백그라운드에서 작업이 되므로 실제 알고리즘이 반환하는 값을 알 수 없으며, 게다가 알고리즘이 잘못되어 무한루프에 걸린경우 (+타임 리밋을 해제한경우)이에대해 컨트롤이 어렵다는 것이다. 이에 대한 보완방법은 이 글의 하단부에 놓을 것이다.
아무튼 이 소스를 타겟파일의 최상위층에 require()하여 사용하면 부하가 큰 작업에 대하여 쉬운 처리가 가능하다. 특이 함수를 사용하는것이 아니기 때문에 이자체와 PHP4, 5 에서 사용가능할것이다. 그리고 작업 환경에 따라서 상단에 set_time_limit(0);를 사용해 주는것도 고려할 만 하겠다.
while(ob_get_level()) ob_end_clean();
header('Connection: close');
ignore_user_abort();
ob_start();
echo('Connection Closed');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
2. 멀티태스킹 구현하기(연결 상에서)
function curl_post_async($url, $params)
{
foreach ($params as $key => &$val) {
if (is_array($val)) $val = implode(',', $val);
$post_params[] = $key.'='.urlencode($val);
}
$post_string = implode('&', $post_params);
$parts=parse_url($url);
$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($post_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if (isset($post_string)) $out.= $post_string;
fwrite($fp, $out);
fclose($fp);
}
보완 가능한 부분 :
위 두 방법의 단점이라 하면 결과값을 받기 전에 클라이언트와 서버에 있어서의 연결이 종료되기 때문에 실제 알고리즘이 반환하는 값에대해서는 트래킹이 불가능하다는 것이다. 하지만 이 점은 약간의 보완을 통해 해결할 수 있는데, 바로 프로그램을 실행하기 전에 DB와 ID값을 사용하여, 알고리즘 종료시 DB에 결과값을 저장하고, 클라이언트 측에서 지속적으로 ID값을 사용하여 결과값을 확인하게 하는것이다.
그리고 위에 있는 멀티태스킹을 구현한 함수에서의 문제라면 fsockopen함수는 lookup과정과 연결확립이 완료 된 후에 뒤에 있는 작업들을 처리할 수 있다는 점이다. 그렇기 때문에 PHP5에서 제공하는 stream_socket_client라는 함수를 사용하여 더욱 더 비동기적인 작업의 처리가 가능할 것이다.
소스 출처 : http://stackoverflow.com/questions/124462/asynchronous-php-calls
내용 출처 : http://frontjang.info/entry/PHP-Background-task-Multitasking-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0
'개발 > PHP' 카테고리의 다른 글
PHP5와 PHP7 차이점 (0) | 2020.10.04 |
---|