OJkP1N.png

主要介绍下 Console 内核与下面两者的使用:

  • Artisan
  • Job

Console 内核

首先理解 app/Console/Kernel 的作用

$commands 属性定义了手动加载的命令

1
2
3
4
protected $commands = [
Commands\ReserveExpired::class,
Commands\TestCommand::class
];

commands() 方法中引入自动加载命令的文件

1
2
3
4
protected function commands()
{
require base_path('routes/console.php');
}

schedule() 方法中定义定时任务

有如下几种方式:

  • Closure 闭包
1
2
3
$schedule->call(function () {
DB::table('should_delete')->delete();
})->daily();
  • Shell 命令
1
$schedule->exec('node /home/forge/script.js')->daily();
  • Artisan
1
$schedule->command('reserve-expired')->dailyAt('02:00');
  • Job
1
$schedule->job(new ReceiveMoney)->everyFiveMinutes();

OJkt8L.png

Artisan

新建一个预约已过期命令:

1
php artisan make:command ReserveExpired

命令结构如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace App\Console\Commands;

use Illuminate\Console\Command;
use Reserve;

class ReserveExpired extends Command
{
//使用时期望输入的命令
protected $signature = 'reserve-expired';

//命令描述
protected $description = 'change expired reserve state';

//主方法
public function handle()
{
$reserve = new Reserve();
$reserve->updateStateWhenExpired();
}
}

获取输入

1
2
$name = $this->ask('What is your name?');
$password = $this->secret('What is the password?');

请求确认

1
2
3
if ($this->confirm('Do you wish to continue?')) {
//
}

颜色

1
2
3
$this->info('Success');
$this->error('Fail');
$this->line('Hello world');

定义输入期望

signature 属性中定义期望用户输入的内容

  • 花括号 {} 为必须
  • 加问号 {?} 为可选
  • 加等号 {=xx} 为带默认值的可选
1
protected $signature = 'wechat-menu {type?} {officialType?}';

当输入不符合时,直接返回提示信息:

1
2
3
4
5
6
7
$usageString = <<<USAGE
Usage: wechat-menu [options] [officialType]

options args: create/get
officialType args: one/two/three
USAGE;
$this->info($usageString);

OJkRDC.png

Queue

本次选择阿里云上提供的 RocketMQ,并使用 freyo/laravel-queue-rocketmq

config/queue.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
'connections' => [
'rocketmq' => [
'driver' => 'rocketmq',
'access_key' => env('ROCKETMQ_ACCESS_KEY'),
'access_id' => env('ROCKETMQ_ACCESS_ID'),
'endpoint' => env('ROCKETMQ_ENDPOINT'),
'instance_id' => env('ROCKETMQ_INSTANCE_ID'),
'group_id' => env('ROCKETMQ_GROUP_ID'),
'queue' => env('ROCKETMQ_QUEUE'),
'use_message_tag' => env('ROCKETMQ_USE_MESSAGE_TAG', false),
'wait_seconds' => env('ROCKETMQ_WAIT_SECONDS', 0),
'plain' => [
'enable' => false,
'job' => 'App\Jobs\RocketMQPlainJobHandler@handle',
],
],
],

创建任务

1
php artisan make:job ReceiveMoney

在构造类中声明需要接收的参数,使用 dispatch 分发它,并指定队列:

1
ReceiveMoney::dispatch($data, $type)->onQueue(env('ROCKETMQ_TOPIC_JOB'));

运行队列

1
2
3
4
# 常驻
php artisan queue:work
# 单次
php artisan queue:work --once

失败处理

failed 配置队列中的任务执行失败时,保存失败任务的库与表,并用命令创建:

1
2
php artisan queue:failed-table
php artisan migrate

手动查看与操作失败任务:

1
2
3
4
5
6
7
8
9
10
# 以表格展示
php artisan queue:failed
# 重试单个ID
php artisan queue:retry 1
# 重试全部
php artisan queue:retry all
# 删除单个ID
php artisan queue:forget 2
# 删除全部
php artisan queue:flush

在运行时指定自动重试次数 --tries,例如 3 次:

1
php artisan queue:listen --queue=common --tries=3

在类中定义一个重试时间方法,例如第一次 10 秒,第二次 1 分钟,第三次 5 分钟:

1
2
3
4
public function backoff()
{
return [10, 60, 300];
}

完整的运行示例:

1
php artisan queue:listen --queue=common --delay=1 --sleep=3 --tries=3 --timeout=600 --quiet | bash >> /var/log/message_common.log 2>&1

平时在遇到数据延迟时要及时查看队列状态