【问题标题】:How to sleep PHP(Laravel 5.2) in background如何在后台休眠 PHP(Laravel 5.2)
【发布时间】:2017-05-03 12:30:20
【问题描述】:

我创建了一个artisan command,我想在调用方法后立即运行它。但是该命令包含一个sleep(); 命令。我想在后台运行那个 artisan 命令,因为该方法需要return 立即响应用户。我的示例代码如下:

在路由文件中

Route::get('test', function(){
    Artisan::queue('close:bidding', ['applicationId' => 1]);
    return 'called close:bidding';
});

close:bidding 命令中

public function handle()
    {
        $appId = $this->argument('applicationId');
        //following code line is making the problem
        sleep(1000 * 10);
        //close bidding after certain close time
        try{
            Application::where('id', $appId)->update(['live_bidding_status' => 'closed']);
        }catch (\PDOException $e){
            $this->info($e->getMessage());//test purpose
        }
        $this->info($appId.":  bid closed after 10 seconds of creation");
    } 

问题 当我点击/test url 时,返回字符串called close:bidding 在浏览器加载10 秒后显示,因为命令中有sleep(10 * 1000)

我想要什么 我想在后台运行命令。我的意思是当我点击/test url 时,它应该立即显示called close:biddingclose:bidding 命令将在后台运行。 10 秒后,它会更新应用程序,但前端用户不会注意到任何有关它的信息。

部分问题

  1. 它是否与multi threading有某种关系?

  2. 是不是用 PHP 解决不了的问题,我应该换个思路吗?

  3. 使用 Laravel 队列有没有办法解决这个问题?

【问题讨论】:

  • 也许你可以试试 laravel 队列作业而不是命令
  • 谢谢,我试试

标签: php multithreading laravel-5 sleep


【解决方案1】:

创建工作

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class JobTest implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    private $payload = [];
    public function __construct($payload)
    {
        $this->payload = $payload;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $appId = $this->payload('applicationId');
        //following code line is making the problem
        sleep(1000 * 10);
    }
}

推送作业后台队列

Route::get('test', function(){
    dispatch((new JobTest)->onQueue('queue_name'));
    return 'called close:bidding';
});

在这种状态下,我们有工作,而您将工作转移到队列中。但它还没有处理。我们需要队列侦听器或工作人员在后台处理这些工作

php artisan queue:listen --queue=queue_name --timeout=0  
OR
php artisan queue:work --queue=queue_name --timeout=0 //this will run forever

注意: 也许您可以尝试使用 supervisord,beanstakd 来管理队列

更多信息请参考this

【讨论】:

  • 你能澄清你的最后一条命令吗?当我创建作业并在队列中分派作业时也会发生这种情况。我没有使用php artisan queue:work --queue=queue_name --timeout=0 命令,因为我不知道它在做什么以及为什么需要它。
  • 更新我的答案可能会有所帮助。或者浏览一下答案中的链接
  • 所以,我需要一个队列侦听器或工作人员来处理我的工作。但是谁来运行queue:listenerqueue:worker 命令呢?
【解决方案2】:

如果您不需要适当队列的所有优势(需要付出代价),使用terminate middleware 可能就足够了。它会在响应发送到浏览器后完成这项工作。

【讨论】:

  • 它会影响对服务器的任何进一步请求吗?
  • @Al-ImranAhmed,我不确定我是否明白这个问题。您有什么特别的顾虑吗?
  • 假设,我点击了一个 url,我得到了响应,然后在提供响应后服务器正在处理另一个任务(在可终止的中间件中)。在那个任务中,我有一个sleep(1000*10) 命令。同时,如果再次向服务器发出请求,前一个请求的可终止任务(sleep)是否会影响新的请求。
  • 我仍然不明白您所说的影响新请求是什么意思。它不会比问题中的原始实现更糟。适用于共享资源的通常限制,例如如果您在一个线程中写锁定一个文件,并在第一个请求释放锁之前尝试在另一个请求中写入同一个文件,那么是的,它会影响。否则 2 个请求由 2 个不干扰的不同进程处理。 terminate 不会改变 php 的工作方式,它只是在执行代码之前刷新输出缓冲区。
  • 我明白了,谢谢。通过affect 这个词我问,因为上一个请求是sleep 命令并且某些东西(可能是PHP)正在休眠一段时间。所以,在那个休眠时间内,如果另一个请求到来,新请求是否必须等到旧请求的休眠时间结束。我的意思是一个小词affect。我的错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-31
  • 1970-01-01
  • 2018-05-22
  • 1970-01-01
  • 2016-06-02
  • 2013-01-25
相关资源
最近更新 更多