PHP에서는 ingore_user_abort () 함수는 종종 사용자가 연결이 끊어진 후 (예 : 브라우저를 닫거나 네트워크를 연결 해제하는 등) 스크립트가 실행을 계속할 수 있도록 사용됩니다. 그러나 많은 개발자들은 사용 중에 효과가 없다는 것을 알게 될 것이며 사용자가 연결을 끊기 때문에 스크립트가 여전히 종료됩니다. 이 기사는이 문제의 원인을 심층적으로 분석하고 몇 가지 일반적인 솔루션을 요약합니다.
INGORE_USER_ABORT () 는 부울 매개 변수를 수용하는 PHP의 내장 함수입니다. 이 기능을 호출하고 True 를 통과 한 후 PHP는 사용자의 연결 끊김 이벤트를 무시하고 현재 스크립트가 완료되거나 적극적으로 종료 될 때까지 현재 스크립트를 계속 실행합니다.
<?php
ignore_user_abort(true);
echo "스크립트가 실행되기 시작합니다\n";
// 시간이 많이 걸리는 작업이 수행되었다고 가정하십시오
sleep(30);
echo "스크립트 실행 종료\n";
?>
위의 코드는 이론적으로 사용자가 브라우저를 닫더라도 계속 실행해야합니다.
PHP의 실행 모드는 다음과 같습니다.
CLI 모드 : 일반적으로 브라우저 연결 개념이 없기 때문에 사용자가 연결이 끊어지기 때문에 종료되지 않습니다.
CGI/FASTCGI 모드 : 웹 서버 구성에 의해 제한 될 수 있으며 사용자 연결을 완전히 무시할 수는 없습니다.
APACHE MOD_PHP : 일반적으로 INGORE_USER_ABORT가 지원되지만 구성에주의를 기울여야합니다.
스크립트에 출력 버퍼가있는 경우 서버는 브라우저가 분리 된 시점에 서버를 감지하지 않으므로 PHP 프로세스가 분리 이벤트를 정확하게 알지 못하여 설정을 무시합니다.
해결책 : 출력 버퍼를 끄거나 새로 고침하십시오.
<?php
ignore_user_abort(true);
ob_end_flush(); // 출력 버퍼링을 끕니다
flush(); // 출력을 브라우저로 보냅니다
sleep(30);
?>
PHP 구성의 max_execution_time은 스크립트의 최대 실행 시간을 제한하며 도착 시간 후에 스크립트가 종료됩니다.
해결책 : max_execution_time을 조정하거나 전화하십시오
<?php
set_time_limit(0); // 스크립트 실행 시간 제한을 취소합니다
ignore_user_abort(true);
?>
일부 웹 서버 또는 리버스 프록시 (예 : NGINX)는 분리 요청을 적극적으로 종료하여 PHP 프로세스가 종료 신호를 수신하게합니다.
해결책:
서버 및 에이전트의 시간 초과 설정을 확인하십시오.
장기 PHP 스크립트를 대체하려면 비동기 작업 대기열 또는 배경 데몬을 사용하십시오.
<?php
ignore_user_abort(true);
echo "작업 실행을 시작하십시오\n";
sleep(30);
echo "미션이 끝납니다\n";
?>
브라우저가 연결이 끊어지면 출력이 즉시 전송되지 않아 스크립트가 중단 될 수있어 서버가 모니터링 할 수 없습니다.
<?php
ignore_user_abort(true);
set_time_limit(0);
echo "작업 실행을 시작하십시오\n";
ob_end_flush();
flush();
sleep(30);
echo "미션이 끝납니다\n";
?>
질문 | 해결책 |
---|---|
스크립트는 사용자 연결이 끊어져 종료됩니다 | ingore_user_abort (true) |
스크립트 실행 시간은 제한적입니다 | set_time_limit (0) |
출력이 즉시 전송되지 않아서 분리가 감지됩니다. | 출력 버퍼링 OB_END_FLUSH ()를 끄고 flush () 를 호출합니다. |
서버 시간 초과 또는 프록시 제한 | 서버 구성을 조정하고 배경 작업 방법을 사용하십시오 |
INGORE_USER_ABORT ()는 전능하지 않으며, 특히 복잡한 서버 환경에서는이 기능을 호출한다고해서 스크립트를 지속적으로 실행하도록 보장 할 수는 없습니다. 합리적인 출력 제어를 결합하면 실행 시간 설정 및 서버 구성이 이상적인 결과를 얻을 수 있습니다. 동시에 장기 작업의 경우 시스템 안정성 및 확장 성을 향상시키기 위해 메시지 대기열 또는 배경 데몬 설계를 사용하는 것이 좋습니다.
<?php
// 전형적인 사용 시연
ignore_user_abort(true);
set_time_limit(0);
echo "미션이 시작됩니다\n";
ob_end_flush();
flush();
for ($i = 0; $i < 10; $i++) {
// 장기 실행 작업을 시뮬레이션합니다
sleep(3);
echo "일정:$i\n";
flush();
}
echo "작업 완료\n";
?>