PHP의 세션 관리 메커니즘에서 Session_Register_Shutdown () 함수는 비교적 새로운 기능입니다. 콜백 함수를 등록하는 데 사용되며 스크립트가 실행되고 세션이 닫히면 자동으로 호출됩니다. 이 메커니즘의 원래 의도는 요청이 끝날 때 $ _session 에 대한 모든 변경이 안전하게 작성 될 수 있도록하여 스크립트 예외 또는 조기 출구로 인해 세션 데이터의 손실을 피할 수 있도록하는 것입니다.
그러나 실제 생산 환경에서, 특히 Nginx + PHP-FPM과 같은 배포 아키텍처에서 Session_Register_Shutdown () 이 요청이 끝날 때 항상 트리거 될 것이라고 보장 할 수 있는지 여부는 논의 할 가치가 있다고 보장 할 수 있습니다.
PHP는 내부적으로 Session_Start () 에서 "Close Session"후크를 등록하며 스크립트 실행 종료시 세션 데이터를 작성해야합니다. Session_Register_Shutdown ()을 사용하면 사용자가 콜백 함수를 사용자 정의 하여이 실행 프로세스에 추가 할 수 있습니다.
샘플 코드 :
<?php
session_start();
session_register_shutdown(function() {
// 스크립트 끝에서 실행됩니다.,다시 쓰십시오 session
error_log('Session shutdown callback triggered.');
// 여기에서 안전하게 작동 할 수 있습니다 $_SESSION
});
$_SESSION['count'] = ($_SESSION['count'] ?? 0) + 1;
echo "방문 수:" . $_SESSION['count'];
?>
PHP-FPM은 PHP의 FASTCGI 프로세스 관리자이며 주요 기능은 다음과 같습니다.
웹 서버와 독립적으로 실행되며 Nginx의 요청을 수락합니다.
요청이 완료된 후에는 리소스가 재활용되지만 프로세스 자체는 오랫동안 살아남습니다.
이는 PHP의 수명주기가 요청 단위를 기반으로하며 모든 요청 관련 청소 조치가 요청이 끝날 때 트리거됩니다.
일반 요청 프로세스에서 Session_Register_Shutdown () 을 통해 등록 된 콜백이든 PHP 자체의 자동 세션 마감 후크이든 실행됩니다.
그러나 다음과 같은 특별한 상황으로 인해 콜백이 트리거되지 않을 수 있습니다.
PHP 스크립트는 비정상적으로 종료됩니다 . 예를 들어, exit () , die () 가 호출되거나 치명적인 오류로 인해 스크립트가 중단되면 대부분의 청소 기능이 여전히 실행되지만 일부 비정상적인 달리기 환경으로 인해 후크가 실행되지 않을 수 있습니다.
요청은 NGINX 또는 PHP-FPM에 의해 종료되어야합니다 . 프로세스가 시작되거나 프로세스가 수동으로 사망 한 경우 PHP 스크립트가 실행되지 않습니다.
CORMICTION ARVERS의 PASTCGI : 요청이 닫히거나 재 시도되면 PHP 프로세스는 실행 프로세스를 정상적으로 완료하지 않습니다.
FASTCGI_FINISH_REQUEST ()가 사용됩니다 .이 함수는 요청 응답을 미리 종료하고 후속 코드가 여전히 실행되지만 후크가 요청의 끝에 의존하면 타이밍이 부정확 할 수 있습니다.
따라서 대부분의 경우 Session_Register_Shutdown () 이 트리거되지만 요청이 끝날 때 100% 실행되는 것은 보장되지 않습니다.
주요 비즈니스 로직을 완료하려면 Session_Register_Shutdown () 에 의존하지 마십시오 . 중요한 세션 데이터 작성 작업은 요청 도중 또는 스크립트에서 최대한 많이 완료해야합니다.
오류 처리 메커니즘과 협력하십시오 : register_shutdown_function () 및 오류 캡처 메커니즘을 사용하여 예외 중단으로 인한 데이터 손실을 방지하십시오.
PHP 및 NGINX 타임 아웃 매개 변수를 합리적으로 설정하십시오 . 요청의 강제 중단을 피하고 스크립트가 정상적으로 실행되는지 확인하십시오.
테스트 환경 시뮬레이션 예외 : 콜백 실행의 신뢰성을 확인하고 응용 프로그램의 견고성을 확인하십시오.
다음은 session_register_shutdown () 과 예외 처리를 결합한 단순화 된 예입니다.
<?php
session_start();
session_register_shutdown(function() {
error_log('Session shutdown callback executed.');
session_write_close();
});
register_shutdown_function(function() {
$error = error_get_last();
if ($error !== null) {
error_log('Fatal error captured: ' . print_r($error, true));
// 다음은 몇 가지 치료 작업입니다,예를 들어, 로깅 또는 경고
}
});
try {
$_SESSION['user'] = 'Alice';
// 예외를 시뮬레이션하십시오
// throw new Exception("Something went wrong!");
} catch (Exception $e) {
error_log('Exception caught: ' . $e->getMessage());
// 예외 처리 로직
}
echo "Session updated.";
?>