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()
改用 fwrite
或 file_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);