我有一个项目需要通过WebSockets不断发送通知。它应该连接到以字符串格式返回总体状态的设备。系统对其进行处理,然后根据各种条件发送通知。
由于调度程序最早可以一分钟重复一个任务,所以我需要找到一种每秒执行该函数的方法。
这是我的
app/Console/Kernel.php
:
<?php
...
class Kernel extends ConsoleKernel
{
...
protected function schedule(Schedule $schedule)
{
$schedule->call(function(){
// connect to the device and process its response
})->everyMinute();
}
}
PS:如果您有更好的想法来处理这种情况,请分享您的想法。
通常,当你想要超过 1 分钟的粒度时,你必须编写一个守护进程。
我建议你尝试一下,现在不像几年前那么难了。只需从 CLI 命令中的一个简单循环开始:
while (true) {
doPeriodicStuff();
sleep(1);
}
一件重要的事情:通过 supervisord 运行守护进程。您可以查看有关 Laravel 队列侦听器设置的文章,它使用相同的方法(守护进程+supervisord)。配置部分可以如下所示:
[program:your_daemon]
command=php artisan your:command --env=your_environment
directory=/path/to/laravel
stdout_logfile=/path/to/laravel/app/storage/logs/your_command.log
redirect_stderr=true
autostart=true
autorestart=true
每秒您可以将命令添加到 cron 作业
* * * * * /usr/local/php56/bin/php56 /home/hamshahr/domains/hamshahrapp.com/project/artisan taxis:beFreeTaxis 1>> /dev/null 2>&1
并指挥:
<?php
namespace App\Console\Commands;
use App\Contracts\Repositories\TaxiRepository;
use App\Contracts\Repositories\TravelRepository;
use App\Contracts\Repositories\TravelsRequestsDriversRepository;
use Carbon\Carbon;
use Illuminate\Console\Command;
class beFreeRequest extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'taxis:beFreeRequest';
/**
* The console command description.
*
* @var string
*/
protected $description = 'change is active to 0 after 1 min if yet is 1';
/**
* @var TravelsRequestsDriversRepository
*/
private $travelsRequestsDriversRepository;
/**
* Create a new command instance.
* @param TravelsRequestsDriversRepository $travelsRequestsDriversRepository
*/
public function __construct(
TravelsRequestsDriversRepository $travelsRequestsDriversRepository
)
{
parent::__construct();
$this->travelsRequestsDriversRepository = $travelsRequestsDriversRepository;
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$count = 0;
while ($count < 59) {
$startTime = Carbon::now();
$this->travelsRequestsDriversRepository->beFreeRequestAfterTime();
$endTime = Carbon::now();
$totalDuration = $endTime->diffInSeconds($startTime);
if($totalDuration > 0) {
$count += $totalDuration;
}
else {
$count++;
}
sleep(1);
}
}
}
$schedule->call(function(){
while (some-condition) {
runProcess();
}
})->name("someName")->withoutOverlapping();
根据您的
runProcess()
执行所需的时间,您可以使用sleep(seconds)
进行更多微调。
some-condition
通常是一个标志,您可以随时更改它以控制无限循环。例如您可以随时使用 file_exists(path-to-flag-file)
手动启动或停止该过程。
我通过在方法
app/Console/Kernel.php
中使用我的schedule()
解决了这个问题:
if (!\Illuminate\Support\Facades\Cache::get('myProcessHeartbeat')) {
$schedule->call(
function () {
while (true) {
\Illuminate\Support\Facades\Cache::put(
'myProcessHeartbeat',
'pulse',
30
);
\Illuminate\Support\Facades\Artisan::call(
'YOUR-COMMAND-HERE'
);
sleep(15);
}
}
);
}
我第一次尝试@Inno解决方案,但如果脚本提前退出,Laravel将等待
24
小时自动删除锁Laravel任务调度 - 防止任务重叠这对我的应用程序来说是致命的。
我的解决方案最多会空闲
1
分钟,并且一次仅运行进程,因为 Laravel 调度运行器被执行为在服务器上每分钟运行一次。
您可以尝试使用 sleep(1) 每秒复制作业 * 60 次。