Laravel 调度作业不异步运行,阻碍执行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39392930/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 14:26:22  来源:igfitidea点击:

Laravel dispatch job doesn't run async, hinders execution

phplaravelasynchronousqueue

提问by Sjoerd de Wit

so in laravel I have a function that posts some content and pushes a job onto a queue and returns some data from the function(not the queue).

所以在laravel中,我有一个函数可以发布一些内容并将作业推送到队列中并从函数(而不是队列)返回一些数据。

Now I thought that laravel queues were supposed to be some sort of async function that makes sure your code remains quick even though there is a lot of data to handle so you put it in a job. But I noticed that my code still needs to wait till the job is finished before it returns data to the user. Here's a log of the script called 2 times but one is with almost no data in the job, and the other has a lot:

现在我认为 Laravel 队列应该是某种异步函数,它可以确保您的代码保持快速,即使有大量数据要处理,因此您将其放入工作中。但是我注意到我的代码仍然需要等到作业完成才能将数据返回给用户。这是一个被调用 2 次的脚本日志,但其中一个在作业中几乎没有数据,另一个有很多:

[2016-09-08 13:26:50] production.INFO: New alert with Image  
[2016-09-08 13:26:50] production.INFO: Push is send.  
[2016-09-08 13:26:50] production.INFO: Alert data is send back.  
[2016-09-08 13:26:50] production.INFO: New image is valid  
[2016-09-08 13:26:50] production.INFO: Move file for upload  
[2016-09-08 13:26:50] production.INFO: Made it to upload  

[2016-09-08 13:28:50] production.INFO: New alert with Image  
[2016-09-08 13:31:19] production.INFO: Push is send.  
[2016-09-08 13:31:19] production.INFO: Alert data is send back.  
[2016-09-08 13:31:20] production.INFO: New image is valid  
[2016-09-08 13:31:20] production.INFO: Move file for upload  
[2016-09-08 13:31:20] production.INFO: Made it to upload  

As you can see the second ones takes 4 minutes before the application receives further data. This is a deal breaker you can't make users wait so long. So how do I get the job to run async and the function doesn't have to wait for it to finish.

如您所见,在应用程序接收更多数据之前,第二个需要 4 分钟。这是一个交易破坏者,你不能让用户等待这么久。那么我如何让工作异步运行并且函数不必等待它完成。

Here's the line where I call the code:

这是我调用代码的行:

if($isValid === true) {
  $this->dispatch(new SendPushNotificationAlert($alert));

  Log::info('Push is send.');
}

And here is my job:

这是我的工作:

<?php

namespace App\Jobs;

use DB;
use Log;
use App\Alerts;
use App\Users;
use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Http\Controllers\PushNotificationsController as PushNotificationsController;

class SendPushNotificationAlert extends Job implements ShouldQueue
{
    use InteractsWithQueue, SerializesModels;
    Protected $alert;
    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(Alerts $alert)
    {
        //
        $this->alert = $alert;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $alert = $this->alert;
        $radius = 10000;
        $earthRadius = 6371000;  // earth's mean radius, m
        // first-cut bounding box (in degrees)
        $maxLat = $alert->lat + rad2deg($radius/$earthRadius);
        $minLat = $alert->lat - rad2deg($radius/$earthRadius);
        // compensate for degrees longitude getting smaller with increasing latitude
        $maxLon = $alert->lon + rad2deg($radius/$earthRadius/cos(deg2rad($alert->lat)));
        $minLon = $alert->lon - rad2deg($radius/$earthRadius/cos(deg2rad($alert->lat)));
        $locations = DB::select("
        SELECT id, lat, lon, user_id, name, radius,
          acos(
            sin(?)*
            sin(radians(lat))+
            cos(?)*
            cos(radians(lat))*
            cos(radians(lon) - ?)
          ) * ? AS distance
              FROM (
                  SELECT id, lat, lon, user_id, name, radius
                  FROM user__locations
                  WHERE lat BETWEEN ? AND ?
                    AND lon BETWEEN ? AND ? AND hide = 0
        ) AS FirstCut
        WHERE acos(
            sin(?)*
            sin(radians(lat))+
            cos(?)*
            cos(radians(lat)
          )*
          cos(radians(lon) - ?)
        ) * ? < ?
        ORDER BY distance", [
          deg2rad($alert->lat),
          deg2rad($alert->lat),
                deg2rad($alert->lon),
          $earthRadius,
                $minLat,
          $maxLat,
          $minLon,
          $maxLon,
          deg2rad($alert->lat),
          deg2rad($alert->lat),
          deg2rad($alert->lon),
          $earthRadius,
          $radius
        ]);

        if(count($locations > 0)) {
          foreach ($locations as $location) {
            if($location->distance < $location->radius) {
              if($alert->anoniem == 0) {
                $user = Users::find($alert->user_id);
                $pushuser = Users::find($location->user_id);
                $pushuser->type = 'location';
                $pushuser->locationname = $location->name;
                $pushusers[] = $pushuser;
              }
                    }
          }
        }
        if(isset($pushusers)) {
          PushNotificationsController::sendPushnotificationsAlert($pushusers, $user);
        }
    }
}

Anyone knows why the job doesn't run async and what I could do to fix it?

任何人都知道为什么这项工作不异步运行以及我可以做些什么来解决它?

采纳答案by Sven Buijsrogge

What queue driver do you use?

您使用什么队列驱动程序?

As described here: https://laravel.com/docs/5.2/queues#introductionyou have multiple options but if you use synchronous(for local environments only) it'll not run Async.

如此处所述:https: //laravel.com/docs/5.2/queues#introduction您有多种选择,但如果您使用synchronous(仅适用于本地环境),它将不会运行异步。

And does your Job implement the Illuminate\Contracts\Queue\ShouldQueue?

你的工作是否实施了Illuminate\Contracts\Queue\ShouldQueue

As described here: https://laravel.com/docs/5.2/queues#writing-job-classesyou'll see that if you don't implement it the job will run synchronously.

如此处所述:https: //laravel.com/docs/5.2/queues#writing-job-classes你会看到如果你不实现它,作业将同步运行。

Hope it'll help!

希望它会有所帮助!

EDIT

编辑

Saw you already implement the Illuminate\Contracts\Queue\ShouldQueue, so that could not be the problem.

看到你已经实现了Illuminate\Contracts\Queue\ShouldQueue,所以这不是问题。

回答by Hyder B.

I have been getting the same issue in Laravel 5.7. By default, Laravel queue is configured to run synchronously. Open config/queue.php, switch to anything else other than sync

我在 Laravel 5.7 中遇到了同样的问题。默认情况下,Laravel 队列配置为同步运行。打开config/queue.php,切换到除sync

For example:

例如:

'default' => env('QUEUE_CONNECTION', 'redis'),

Alternatively, you can also add this to your .env file.

或者,您也可以将其添加到 .env 文件中。

QUEUE_CONNECTION=redis