如何在PHP(Laravel)中调试"SymfonyComponentDebugExceptionFatalErrorException"错误?



我收到了客户端遇到的许多错误的报告

Symfony\Component\Debug\Exception\FatalErrorException

超过的最大执行时间为30秒

我自己无法在本地机器或生产服务器上复制它。这个URL遍布整个网站,所以,我想这是全球性的,比如中间件造成的。

我使用Sentry.io来收集数据,但异常跟踪只有一个条目指向Symfony基本代码中的某个代码,最常见的是:

vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php,位于第73行

vendor/symfony/finder/Iterator/DateRangeFilterIterator.php,位于第45行

vendor/symfony/finder/Iterator/RecursiveDirectoryTerator.php,第69行

很明显,似乎有一些东西与文件系统有关,但由于没有跟踪,我看不到在哪里可以查找站点代码中的错误。我想这是某种无限循环或泄漏,但没有任何痕迹,也没有一致的方法来重现问题。

我应该如何查找问题并调试它?

有没有我可以设置的设置,或者我可以使用/启用的工具?

阅读您的聊天对话后,我发现您正在使用以下.env配置:

CACHE_DRIVER=file 
SESSION_DRIVER=file 

我认为这就是问题所在。。。我更好地解释了自己。

当您将file驱动程序用于缓存或会话时,Laravel将创建大量文件来存储用户会话数据或应用程序缓存数据。。。

如果您的电子商务正在增长并产生大量流量,那么性能可能会因为框架必须扫描的大量文件而放缓。

我认为这可能是两种可能的解决方案:

  • 您的生产环境必须升级(我不知道您的生产服务器规格,也不知道您是否有足够的资源)
  • 文件驱动程序速度太慢,无法满足您的应用程序要求

我通常使用redis作为缓存和会话驱动程序,它更快,而且有一个很好的"智能缓存"策略,这是一个很棒的工具。

如果可能的话,我认为你也应该尽量使用它。Memcached可能也是一个不错的解决方案。

如果您不确定异常的原因,那么您可以用两种方法处理

1增加请求超时ini_set('max_execution_time',60)//60秒=1分钟

2在try-catch 中包装您的代码

try{
//logic goes here
}catch(Excaption $e){
Log::error($e->getMessage().' '. $e->getFile().' '. $e->getLine());
return back()->with('error',$e->getMessage() );
}

您可以注册关闭函数吗?即使发生超时,也会调用关闭函数。有了它,您可以打印或保存您想要的日志文件。我不确定是否有更好的方法在laravel中获取回溯,但我可能会在纯php中这样做(调用debug_backtrace)。

<?php
function timedOut() {
//save to a log file instead of printing
var_dump(debug_backtrace());
}
register_shutdown_function("timedOut");

http://php.net/manual/en/function.register-shutdown-function.php

http://php.net/manual/en/function.debug-backtrace.php

我不习惯Laravel,但我遇到过这个问题,我使用PHP的register_shutdown_function解决了这个问题。

我发现它在跟踪随机发生的错误时非常有用。这就是我在代码中这样做的方式。你可以把它放在一个公共文件的某个地方,这个文件会在每个页面上执行,index.php对你来说是一个很好的选择,因为所有的Laravel路由都经过它(我的假设)。

register_shutdown_function( "check_for_fatal" );
function check_for_fatal(){
$time = time(); //time when this error occurred
$error = error_get_last();
if (in_array($error["type"], [E_ERROR, E_CORE_ERROR, E_RECOVERABLE_ERROR])){
$email_body = [];
$email_body[] = 'Date: ' . date('m-d-Y H:i:s', $time);
ob_start();
var_dump($error);
$email_body[] = ob_get_clean();
//include any other data as needed
//$body[] = "add data as appropriate";
//You can email it to yourself, but if there are lots of errors you will be bombarded with emails
mail('your_email_address@example.com', 'Subject', implode("rn", $email_body));
//or you can save this to some log file
}
}

看起来PHP正在等待一些资源,例如文件访问、数据库、邮件服务器(我认为是文件)。

  • 您是否尝试在一个会话中在多个选项卡上使用您的应用程序
  • 你们有没有试过从多台机器登录到同一个帐户
  • 也许脚本的某个部分是打开文件而不是关闭它
  • 您是否从打开网站开始跟踪用户操作以获得此错误
  • 检查您的生产数据库-可能有很小的连接限制

编辑

我看到您正在使用dannyvankooten/vat.php库,它向外部服务发出一些请求。这可能是你问题的根源。这个库正在使用curl进行请求。Author正在设置CURLOPT_CONNECTTIMEOUT,但未设置CURLOPT_TIMEOUT,您的脚本有时会等待比max_execution_time设置限制的时间更长的时间。

我认为您现在还不应该增加超时时间。如果你做"尝试捕捉",你可能会了解潜在的问题。如果没有,请检查在特定方法或类中执行的操作/函数。您可能正在查询一个巨大的表,并试图使用这些信息。

如果你做

DB::listen(function ($sql) {
var_dump($sql);
});

这将指示操作正在运行的查询数量

在try-catch中无法捕获此错误,因为它实际上是一个PHP错误,而不是一个异常。

为了能够调试它,你有几个选项:

  1. 在代码中添加一些日志以确定超时位置
  2. 您可以使用Laravel转储服务器包来转储日志。这实际上将与Laravel 5.7一起发货,但您现在可以随时添加包

我安装了laravel-debugbar。我认为它对您有帮助。

composer需要barryvdh/laravel调试器接下来打开config/app.php并在"providers"数组中添加:

BarryvdhDebugbarServiceProvider::class,

在别名数组类中:

'Debugbar' => BarryvdhDebugbarFacade::class,

你可以查看

Debugbar::measure('My long operation', function() {

//做点什么…});

您无法捕获php超时错误。php解释器停止执行时会出现此错误。您只能增加时间限制,例如ini_set('max_execution_time',300)或将长执行工作转换为cron作业,例如laravel任务计划。

一个新的sentine版本将为您提供适当的堆栈跟踪。

您必须使用"getsentine/sentint-php">版本>="2.0">

  • 以下是报告的问题:https://github.com/getsentry/sentry-php/issues/761
  • 以下是要修复的PR:https://github.com/getsentry/sentry-php/pull/763

老实说,最好的方法是安装xdebug并以老派的方式调试它,完成整个请求以找到瓶颈,并试图找出它的来源。Laravel以及其他框架都是为了尽可能平稳地运行而设计的。如果你面临任何此类错误,这意味着你可能只是编码错误。

如果没有更多的信息,也很难给你一个具体的建议。我的建议是,它重新创建Laravel应用程序所面临的环境规范(你可以使用Docker或Vagrant或任何你想到的可行的东西),然后使用xdebug运行以找到问题所在。

相关内容

  • 没有找到相关文章

最新更新