PHP에서 '허용 된 메모리 크기 소진'오류를 안전하게 포착
JSON을 클라이언트에 반환하는 게이트웨이 스크립트가 있습니다. 스크립트에서 나는 set_error_handler 를 사용 하여 오류를 포착하고 여전히 형식화 된 반환을 가지고 있습니다.
'Allowed memory size exhausted'오류가 발생하지만 ini_set ( 'memory_limit', '19T') 와 같은 것으로 메모리 제한을 늘리는 대신 사용자가 많이 사용했기 때문에 다른 것을 시도해야한다고 반환하고 싶습니다. 기억.
치명적인 오류를 포착하는 좋은 방법이 있습니까?
로 이 답변이 제안, 당신은 사용할 수 register_shutdown_function()확인 것이다 콜백을 등록합니다 error_get_last().
@( shut up ) 연산자 또는 ( shut up ) 연산자에 의해 문제가되는 코드에서 생성 된 출력을 계속 관리해야합니다.ini_set('display_errors', false)
ini_set('display_errors', false);
error_reporting(-1);
set_error_handler(function($code, $string, $file, $line){
throw new ErrorException($string, null, $code, $file, $line);
});
register_shutdown_function(function(){
$error = error_get_last();
if(null !== $error)
{
echo 'Caught at shutdown';
}
});
try
{
while(true)
{
$data .= str_repeat('#', PHP_INT_MAX);
}
}
catch(\Exception $exception)
{
echo 'Caught in try/catch';
}
실행되면 Caught at shutdown. 불행히도 ErrorException치명적인 오류가 스크립트 종료를 트리거하고 이후에는 종료 기능에서만 포착되기 때문에 예외 개체가 throw되지 않습니다.
$error원인에 대한 자세한 내용은 종료 기능에서 어레이를 확인 하고 그에 따라 대응할 수 있습니다. 한 가지 제안은 웹 애플리케이션에 대해 요청을 다시 발행하고 ( 다른 주소 또는 다른 매개 변수를 사용 하여) 캡처 된 응답을 반환하는 것입니다.
나는 유지하는 것이 좋습니다 error_reporting()높은 ( 값-1 생각을)과 (사용하여 다른 제안으로 와 다른 모든 것들에 대한) 오류 처리를 set_error_handler()하고 ErrorException.
이 오류 (로깅, 향후 디버그를위한 컨텍스트 백업, 이메일 전송 등)가 발생할 때 비즈니스 코드를 실행해야하는 경우 종료 기능을 등록하는 것만으로는 충분하지 않습니다. 메모리를 확보해야합니다.
한 가지 해결책은 어딘가에 비상 메모리를 할당하는 것입니다.
public function initErrorHandler()
{
// This storage is freed on error (case of allowed memory exhausted)
$this->memory = str_repeat('*', 1024 * 1024);
register_shutdown_function(function()
{
$this->memory = null;
if ((!is_null($err = error_get_last())) && (!in_array($err['type'], array (E_NOTICE, E_WARNING))))
{
// $this->emergencyMethod($err);
}
});
return $this;
}
당신이 memory_get_peak_usage의 문서화가에있는이 기능을 사용하여 이미 프로세스가 사용하는 메모리의 크기를 얻을 수 http://www.php.net/manual/en/function.memory-get-peak-usage.php 나는 것 같아 프로세스가 메모리 제한에 거의 도달하기 전에 프로세스를 리디렉션하거나 중지하는 조건을 추가 할 수 있다면 더 쉽습니다. :)
@ alain-tiemblo 솔루션은 완벽하게 작동하지만이 스크립트는 객체 범위를 벗어난 PHP 스크립트에서 일부 메모리를 예약 할 수있는 방법을 보여주기 위해 넣었습니다.
짧은 버전
// memory is an object and it is passed by reference
function shutdown($memory) {
// unsetting $memory does not free up memory
// I also tried unsetting a global variable which did not free up the memory
unset($memory->reserve);
}
$memory = new stdClass();
// reserve 3 mega bytes
$memory->reserve = str_repeat('❤', 1024 * 1024);
register_shutdown_function('shutdown', $memory);
전체 샘플 스크립트
<?php
function getMemory(){
return ((int) (memory_get_usage() / 1024)) . 'KB';
}
// memory is an object and it is passed by reference
function shutdown($memory) {
echo 'Start Shut Down: ' . getMemory() . PHP_EOL;
// unsetting $memory does not free up memory
// I also tried unsetting a global variable which did not free up the memory
unset($memory->reserve);
echo 'End Shut Down: ' . getMemory() . PHP_EOL;
}
echo 'Start: ' . getMemory() . PHP_EOL;
$memory = new stdClass();
// reserve 3 mega bytes
$memory->reserve = str_repeat('❤', 1024 * 1024);
echo 'After Reserving: ' . getMemory() . PHP_EOL;
unset($memory);
echo 'After Unsetting: ' . getMemory() . PHP_EOL;
$memory = new stdClass();
// reserve 3 mega bytes
$memory->reserve = str_repeat('❤', 1024 * 1024);
echo 'After Reserving again: ' . getMemory() . PHP_EOL;
// passing $memory object to shut down function
register_shutdown_function('shutdown', $memory);
출력은 다음과 같습니다.
Start: 349KB
After Reserving: 3426KB
After Unsetting: 349KB
After Reserving again: 3426KB
Start Shut Down: 3420KB
End Shut Down: 344KB
'IT TIP' 카테고리의 다른 글
| 누군가 Erlang에서 Pid의 구조를 설명 할 수 있습니까? (0) | 2020.11.24 |
|---|---|
| 생성자에서 추가 매개 변수와 함께 Ninject를 사용하여 인스턴스 만들기 (0) | 2020.11.24 |
| Amazon S3 스타일 API를 로컬로 제공하는 서버가 있습니까? (0) | 2020.11.24 |
| 기본 멤버 값 모범 사례 (0) | 2020.11.24 |
| git log를 에뮬레이트하는 방법 --decorate의 분기 유형별로 다른 색상 (0) | 2020.11.24 |