[PHP]请求接口后直接返回信息,同时server端继续执行脚本

场景:请求接口,开始执行服务器端其他任务,该接口不需要获得任务执行的结果,只需要启用任务即可返回。

方式1:Process的超时方式实现

Symfony提供的Process支持调用执行外部命令,并可同步、异步方式进行操作。
但需注意Process的异步(async)方式,也必须有$process->wait()等待任务执行才能退出。
这里利用Process的超时特性,设置超时后在时间到期后,将抛出Runtimeexception异常,但后台任务可以继续执行。

1
2
3
4
5
6
7
8
9
10
11
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\RuntimeException;

try {
$process = new Process('cd /home/work/www/activity;nohup /home/work/bin/php artisan activity:couponupdate --activity_id='. $activity_id.' &');
$process->setTimeout(1);
$process->run();
} catch (RuntimeException $e){
\Log::info('hello:');
}
return 'done';

方式2:fastcgi_finish_request()方式实现

利用php-fpm的fastcgi_finish_request()函数直接结束并返回fastcgi,但php脚本继续执行。

1
2
3
4
echo 'update task is running';
fastcgi_finish_request(); // 请求直接返回空,后面继续执行更新券信息操作
//Artisan::call('activity:couponupdate', ['--activity_id' => $activity_id]);
exec('cd /home/work/www/activity;nohup /home/work/bin/php artisan activity:couponupdate --activity_id=' . $activity_id . ' &');

后台任务两种方式和区别:

  • Artisan::call方式:保持在Laravel内执行,依然保持在php-fpm进程中,fpm进程数限制可有效控制后台任务数,但无法区分具体哪个php-fpm进程正在执行artisan命令
  • exec方式:启动外部进程,通过ps -ef | grep artisan可以定位后台任务数量

参考

Symfony: The Process Component
使用fastcgi_finish_request提高页面响应速度
How to Make Async Requests in PHP