Laravel 6.10 应用程序在本地运行但在生产服务器上失败 "Target class [] does not exist."

Laravel 6.10 Application works locally but fails on production server with "Target class [] does not exist."

这个问题专门针对Laravel 6.10和队列处理。在我的本地机器上,程序 运行 运行良好,所有排队的作业加载良好并完成。在我的 GoDaddy 服务器上,当作业尝试加载时出现神秘错误:

Error thrown on line 805 in /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Container/Container.php with message:
    Target class [] does not exist.

Trace:
#0 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Container/Container.php(681): Illuminate\Container\Container->build(NULL)
#1 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Container/Container.php(629): Illuminate\Container\Container->resolve(NULL, Array)
#2 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(776): Illuminate\Container\Container->make(NULL, Array)
#3 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(215): Illuminate\Foundation\Application->make(NULL)
#4 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(88): Illuminate\Queue\Jobs\Job->resolve(NULL)
#5 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(354): Illuminate\Queue\Jobs\Job->fire()
#6 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(300): Illuminate\Queue\Worker->process('database', Object(Illuminate\Queue\Jobs\DatabaseJob), Object(Illuminate\Queue\WorkerOptions))
#7 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(134): Illuminate\Queue\Worker->runJob(Object(Illuminate\Queue\Jobs\DatabaseJob), 'database', Object(Illuminate\Queue\WorkerOptions))
#8 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(112): Illuminate\Queue\Worker->daemon('database', 'default', Object(Illuminate\Queue\WorkerOptions))
#9 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(96): Illuminate\Queue\Console\WorkCommand->runWorker('database', 'default')
#10 [internal function]: Illuminate\Queue\Console\WorkCommand->handle()
#11 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(32): call_user_func_array(Array, Array)
#12 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Container/Util.php(36): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#13 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(90): Illuminate\Container\Util::unwrapIfClosure(Object(Closure))
#14 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(34): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#15 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Container/Container.php(590): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#16 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Console/Command.php(201): Illuminate\Container\Container->call(Array)
#17 /home/jaredclemence/public_html/theninjaassistant.com/vendor/symfony/console/Command/Command.php(255): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#18 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Console/Command.php(188): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#19 /home/jaredclemence/public_html/theninjaassistant.com/vendor/symfony/console/Application.php(1011): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#20 /home/jaredclemence/public_html/theninjaassistant.com/vendor/symfony/console/Application.php(272): Symfony\Component\Console\Application->doRunCommand(Object(Illuminate\Queue\Console\WorkCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#21 /home/jaredclemence/public_html/theninjaassistant.com/vendor/symfony/console/Application.php(148): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#22 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Console/Application.php(93): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#23 /home/jaredclemence/public_html/theninjaassistant.com/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(131): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#24 /home/jaredclemence/public_html/theninjaassistant.com/artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#25 {main}

我相信问题开始了,并且会通过修复项目 #4 中的跟踪来解决,其中调用了以下内容:Illuminate\Queue\Jobs\Job->resolve(NULL)。我在 GoDaddy 服务器上的两个失败作业中都看到了这一点,但它不会在本地发生。我对 laravel 的了解还不够,无法理解 NULL 值的来源以及如何修复它。这发生在加载作业 class 之前,但不会发生在所有排队的作业中。仅此 class.

的职位

在本地副本和生产副本中,我都使用 GoDaddy 数据库,因此两个系统都与同一个数据库主机通信。我使用名为 CMP_dev 和 CMP_core 的数据库来区分开发和生产 table。因为我使用相同的数据库源,所以我可以排除 mysql 设置中的更改。

我升级了所有作曲家包并重新测试。然后,我提交了 composer.lock 文件并更新了 GoDaddy 服务器以匹配。所以,我可以排除已经被其他人修复的旧错误代码的问题。

服务器上的PHP版本是7.3.11,本地dev上的PHP版本是7.3.6。好消息是它们都是 7.3.X,这降低了语言变化的风险,但 7.3.6 和 7.3.11 之间仍然可能存在问题,但 GoDaddy 不允许我控制 PHP 设置超出 7.3 的次要版本号。

---- 添加于 2020 年 1 月 9 日----- 我认为这可能是网络服务器的差异。在我的本地机器上,我使用 php artisan serve 来托管软件。在 GoDaddy 上,我使用 Nginx。但是,后来我意识到 运行 队列不是服务器。命令行 运行 进入队列,两个命令都在 运行 使用 php artisan schedule:run。这排除了 Web 服务器软件及其所有组件。 ---------

我已成功 运行 排队邮件作业,这意味着队列可以正常工作。这应该将问题定位到对我产生问题的两个 classes。如果我能找到一个问题,我很可能会找到第二个问题,所以我将在此处包括第一个导致问题的工作:

app/Jobs/ConvertCsvFileToIntermediateFile.php:

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\ContactCsvFile;
use Illuminate\Support\Facades\Log;

class ConvertCsvFileToIntermediateFile implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    public $timeout = 500;

    /** @var ContactCsvFile */
    private $file;
    private $delegate;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(ContactCsvFile $file, $delegate = null)
    {
        $this->file = $file;
        $this->delegate = $delegate;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $this->file->process($this->delegate);
    }

}

错误发生在调用 handle() 之前。我知道这一点是因为,当我将 dd($this->file) 作为句柄的第一行时,该行永远不会到达。

此外,我认为重要的是要注意,当大多数作业失败时,它们的 class 名称会列在 queue:failed table 中。但在这种情况下,queue:failed table 读取时间:“2020-01-08 09:23:23”。

+----+------------+---------+---------------------+-----------+  
| ID | Connection | Queue   | Class               | Failed At |  
+----+------------+---------+---------------------+-----------+   
| 2  | database   | default | 2020-01-08 09:23:23 |           |   
+----+------------+---------+---------------------+-----------+   

您必须阅读 laravel 6.10 发行说明。一些功能已弃用并已修复。 我认为您必须添加 php unit 9 而不是 v8 not supported 并将其添加到 composer required not dev

我仍然不知道错误的含义或如何修复它。但是,我找到了解决该问题的方法,我将在此处进行描述,以防其他人遇到此问题。

我开始怀疑 queue:failed table 中出现的 st运行ge 数据库条目表明发生了一些可怕的事情导致程序在执行过程中失败,这可能导致部分写入数据库。作为一个合乎逻辑的解决方案,这对我来说没有意义,因为我在 t运行saction 中有作业 运行,应该在失败时回滚。

也就是说,我研究了一个潜在的内存膨胀问题和一个超时问题。我一直遇到超时问题,但是 classes 已经设置为 public $timeout = 500;,这应该在作业失败前 gua运行tee 整整 500 秒(这些作业失败了不到一分钟)。尽管 class 允许 500 秒,但 GoDaddy 可以限制进程运行的时间量,因此进程可能花费了太长时间。

GoDaddy 还可以限制每个进程允许的内存量。由于这些作业处理大量数据,因此可以通过为每个项目创建一个作业而不是创建一个作业来迭代数组来解决时间长度问题和内存膨胀问题。

这就是我解决问题的方法。我确实创建了一个只处理一个项目的作业。我没有将整个数组发送到一个作业,而是迭代数组并将每个项目发送到一个作业。我认为这会增加系统处理每个项目所花费的时间,因为程序在加载时必须 bootstrap 每个作业的应用程序,现在我有数百个作业,而不是一个。但是,如果总时间增加,处理单个作业的时间肯定会减少,因为作业只处理了一个项目,然后关闭。进行此更改后,GoDaddy 服务器不再抛出 NULL 错误,并且一切正常 运行。

我也很惊讶地发现较小的作业也比使用数组的单个作业完成得更快。即使系统必须 bootstrap 每个作业的应用程序,系统 运行 在内存未过载时速度更快。