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

Sjo*_*Wit 8 php queue asynchronous laravel

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

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

[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  
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,第二个需要 4 分钟,应用程序才会收到更多数据。这是一个破坏交易的因素,你不能让用户等待这么久。那么我如何让作业异步运行并且该函数不必等待它完成。

这是我调用代码的行:

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

  Log::info('Push is send.');
}
Run Code Online (Sandbox Code Playgroud)

这是我的工作:

<?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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Hyd*_* B. 6

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

例如:

'default' => env('QUEUE_CONNECTION', 'redis'),
Run Code Online (Sandbox Code Playgroud)

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

QUEUE_CONNECTION=redis
Run Code Online (Sandbox Code Playgroud)


小智 1

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

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

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

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

希望它会有所帮助!

编辑

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

  • 一个非常重要的部分是将 .env QUEUE_DRIVER 更改为(redis、database、sqs),默认情况下是同步的 (2认同)