Storage::append 遇到 Allowed memory size of 134217728 bytes exhausted

API接口响应时,对所有请求的入参和出参进行日志记录,日志文件以天进行分割,实际生产环境中日志写入时出现内存溢出:

[2020-07-21 19:26:58] production.ERROR: Allowed memory size of 134217728 bytes exhausted (tried to allocate 113064726 bytes) {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalErrorException(code: 1): Allowed memory size of 134217728 bytes exhausted (tried to allocate 113064726 bytes) at /**/**/vendor/league/flysystem/src/Util/MimeType.php:209)
[stacktrace]
#0 {main}
"}

检查日志写入的代码,使用 Laravel 中的 Storage::append 进行追加,在当日的日志文件较大时,再写入就出现内存溢出,注释掉之后正常

$disk = Storage::disk('api');
$file_name = date('Y-m-d') . '.log';
$disk->append($file_name, $str);

弃用 Storage::append() 改用 fwritefile_put_contents 方式,对两种方式进行测试:

// file_put_contents
Log::info('file_put_contents start ' . microtime());
file_put_contents(storage_path('logs/api/') . $file_name, $str, FILE_APPEND|LOCK_EX);
Log::info('file_put_contents end ' . microtime());

// fwrite 方式
Log::info('fwrite start ' . microtime());
$handler = fopen(storage_path('logs/api/') . $file_name, 'a+b');
fwrite($handler, $str);
fclose($handler);
Log::info('fwrite end ' . microtime());

分别对写入前后时间进行记录,fwrite的执行效率更高

[2020-07-22 10:11:51] local.INFO: file_put_contents start 0.18496800 1595383911
[2020-07-22 10:11:51] local.INFO: file_put_contents end 0.18636200 1595383911
[2020-07-22 10:11:51] local.INFO: fwrite start 0.18641800 1595383911
[2020-07-22 10:11:51] local.INFO: fwrite end 0.18654600 1595383911

fwrite 在不加锁情况下,并发时,可能出现多个php-fpm同时写入日志文件,导致日志内容混乱(脏数据,dity)。目前处理,暂时使用file_put_contents 进行写入,file_put_contents 可能出现多个 php-fpm 写入的日志顺序颠倒,可以使用 LOCK_EX 模式进行锁定

file_put_contents($file_path, 'content', FILE_APPEND|LOCK_EX);

发表评论

您的电子邮箱地址不会被公开。