【问题标题】:Laravel worker not attempting the job but rather deleting itLaravel 工作人员没有尝试这项工作,而是将其删除
【发布时间】:2020-07-18 11:18:01
【问题描述】:

laravel 5.4
php 7.1.32
主管3.3.1
(我知道...我知道。公司落后了 3 年)

config/queue.php

'database' => [
    'driver' => 'database',
    'connection' => 'queue', // means in config/database.php I have to setup a new connection
    'table' => 'jobs',
    'queue' => 'default',
    'retry_after' => 90,
],

主管配置

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/project/artisan queue:work
autostart=true
autorestart=true
user=root
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/html/project/storage/logs/supervisord.log


场景:调度队列时,jobs 表中会添加一个新行。然后将 Laravel Worker 分配给一个作业,此时 reserved_atattempts 列会更新。作业完成后,行(作业)将被删除。

现在,由于一些神秘的原因,有时工作可以无缝运行,有时有工作但没有分配任何工作人员,并且在瞬间该工作被删除。刚刚发生了什么?此外,这种情况非常断断续续,很难跟踪实际尝试了哪些作业,后来又被此问题删除或刚刚删除。

我已经摸不着头脑了至少一个星期了,请指导我。


编辑
- php artisan queue:restart 广播,主管更新正常运行时间,但问题没有改善。
- 后来,我删除了主管并尝试以手动方式进行php artisan queue:work,甚至删除了该作业而不是尝试它(也没有在 failed_jobs 中插入新数据)。


编辑 (2) - 日志
这是分派作业的函数

public static function sendVoiceCall($instituteSmsSettings, $announcementId, $postUrl, $mobileNumbers)
    {
        Log::debug('Job dispatched');
        dispatch(new SendVoiceCall($instituteSmsSettings, $announcementId, $postUrl, $mobileNumbers));
    }

这是工作

<?php

namespace App\Jobs;

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

class SendVoiceCall implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 3;
    protected $ARR_POST_DATA = array();
    protected $postUrl = '';

    public function __construct($instituteSmsSettings, $announcementId, $postUrl, $mobileNumbers)
    {
        $this->ARR_POST_DATA['username'] = $instituteSmsSettings->username;
        $this->ARR_POST_DATA['token'] = $instituteSmsSettings->token;
        $this->ARR_POST_DATA['announcement_id'] = $announcementId;
        $this->ARR_POST_DATA['plan_id'] = $instituteSmsSettings->plan_id;
        $this->ARR_POST_DATA['caller_id'] = $instituteSmsSettings->caller_id;
        $this->ARR_POST_DATA['contact_numbers'] = $mobileNumbers;
        $this->postUrl = $postUrl;
    }

    public function handle()
    {
        Log::debug('Job started');
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $this->postUrl);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($this->ARR_POST_DATA));
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);

        $sendCallResponse = curl_exec($curl);
        $curlResponse = json_decode($sendCallResponse, true);
        curl_close($curl);

        Log::info('Queue complete. Announcement Id: ' . ($this->ARR_POST_DATA['announcement_id'] ?? ''));
    }
}

这是日志

[2020-04-13 10:17:49] production.DEBUG: Job dispatched  
[2020-04-13 10:17:50] production.DEBUG: Job started  
[2020-04-13 10:17:50] production.INFO: Queue complete. Announcement Id: 203691 

如您所见,队列同时开始和结束(应该有 2-3 秒的差异。worker 正在删除作业而不是尝试它

【问题讨论】:

  • 你有 failed_jobs 表吗?如果是,它是否会填充这些缺失的工作?是否存在代码本身产生的错误以某种方式被吞噬的情况,例如通过 try-catch 块,其中 catch 什么都不做?
  • @GeorgeKoniaris failed_jobs 表是空的,即使丢失的作业被删除。我已将 try catch 块添加到我的代码中,但没有引发错误。我还添加了用于调试目的的日志,但代码工作正常,因为 dispatch() 代码添加到作业表中。主管日志中也没有抛出错误。
  • 您可以尝试禁用autorestart 并再次执行吗?我很好奇为什么您的failed_jobs 表和主管日志文件中都没有日志记录。我的第一个猜测是段错误问题。很少发生在我身上,但遗憾的是它不时发生。特别是因为您使用的是带有 PHP7+ 的旧 L5 版本。你能用准确的 PHP 版本在本地重现它吗?
  • 您应该将日志添加到您的 Job 类以查看会发生什么。
  • 只是重申已经提出的建议,因为您还没有在这里明确排除它 - 最简单的解释是该作业确实运行,不会产生任何输出或任何错误,并正常完成。您是否 100% 确定这不会发生?添加日志记录作为代码执行的第一件事,以便您可以查看它是否启动。我注意到的一件事是你有user=root,这通常是你的网络服务器运行的用户,root 真的正确吗?也许某些输出文件或日志在某些情况下以 root 身份创建,导致以后出现写入问题?

标签: php laravel queue supervisord


【解决方案1】:

您的工作是发出 curl 请求,但不处理或检查该调用。请求可能由于某种原因失败,但这项工作永远不会告诉你。特别是现在,当出现无法解释的问题时,对请求和响应进行一些基本的错误检查是有意义的。

您可以检查几件事。一旦你解决了这个特定的问题,可能就不需要做所有这些了,但你可能应该至少使用其中一个来密切关注这个电话。

  • 使用curl_error()检查通话是否有效;

  • 使用curl_getinfo() 向您显示网络请求和响应的详细信息。这将为您提供大量信息,包括 http_response,您可以测试它是 200 或任何您期望的;

  • 如果远程服务器响应一些消息 - 大概是因为您正在 json_decode()ing 它 - 记录它。如果响应中有某种成功/失败元素,请对其进行测试,确保它符合您的预期;

例如(如前所述,您通常不会做所有这些,只需选择适合您情况的):

$curl = curl_init();
// ... your code

// Get request info as an array
$info = curl_getinfo($curl);

$sendCallResponse = curl_exec($curl);
curl_close($curl);

// Log the actual response from the remote server
Log:info('Curl response: ' . $sendCallResponse);

// Log extensive info about the request/response, good when troubleshooting
Log:info('Curl info: ' . print_r($info, true));

// Maybe check the http response code
if ($info['http_code'] !== 200) {
    // handle an error, send a notification, etc
    Log:info('Whoah, remote server responded with ' . $info['http_code']);
}

// Maybe check if curl returned an error
if ($sendCallResponse === false) {
    // handle an error, send a notification, etc
    Log:info('Oh noes, curl error! ' . curl_error($curl));
}

// Maybe test the actual response, if there is something testable in it, 
// say a "status":
if ($curlResponse['status'] !== 'OK') {
    // handle an error, send a notification, etc
    Log:info('Remote returned status ' . $curlResponse['status']);
}

【讨论】:

  • 你是对的。响应中有一个 curl 错误。感谢@Don't Panic 指导我并帮助我了解请求和响应的基本错误检查。赏金是你的。谢谢。
猜你喜欢
  • 1970-01-01
  • 2018-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-08
  • 2019-10-16
  • 1970-01-01
  • 2016-05-29
相关资源
最近更新 更多