12

对于耗时的任务(电子邮件发送、图像处理……你明白了),我想运行异步 PHP 任务。

在 Linux 上这很容易,但我正在寻找一种也适用于 Windows 的方法。

我希望它很简单,因为它应该是。没有大炮,没有 SQL 排队,没有一次又一次地安装东西……我只想运行一个该死的异步任务。

所以我尝试了Symfony Process Component。问题是,同步运行任务可以正常运行,但是当异步运行它时,它会沿着主脚本退出。

有没有办法来解决这个问题?


composer require symfony/process

索引.php

<?php
require './bootstrap.php';
$logFile = './log.txt';

file_put_contents($logFile, '');

append($logFile, 'script (A) : '.timestamp());

$process = new Process('php subscript.php');
$process->start(); // async, subscript exits prematurely…
//$process->run(); // sync, works fine

append($logFile, 'script (B) : '.timestamp());

下标.php

<?php
require './bootstrap.php';
$logFile = './log.txt';

//ignore_user_abort(true); // doesn't solve issue…

append($logFile, 'subscript (A) : '.timestamp());
sleep(2);
append($logFile, 'subscript (B) : '.timestamp());

引导程序.php

<?php
require './vendor/autoload.php';
class_alias('Symfony\Component\Process\Process', 'Process');

function append($file, $content) {
    file_put_contents($file, $content."\n", FILE_APPEND);
}

function timestamp() {
    list($usec, $sec) = explode(' ', microtime());
    return date('H:i:s', $sec) . ' ' . sprintf('%03d', floor($usec * 1000));
}

结果

script (A) : 02:36:10 491
script (B) : 02:36:10 511
subscript (A) : 02:36:10 581
// subscript (B) is missing
4

3 回答 3

1

当异步过程完成时,主脚本必须等待。试试这个代码:

$process = new Process('php subscript.php');
$process->start();
do {
    $process->checkTimeout();
} while ($process->isRunning() && (sleep(1) !== false));
if (!$process->isSuccessful()) {
   throw new \Exception($process->getErrorOutput());
}
于 2015-03-24T11:26:07.490 回答
1

如果php 支持 Windows 的 fpm,您可以在发送响应后监听kernel.terminate事件以提供所有昂贵的任务。

服务:

app.some_listener:
    class: SomeBundle\EventListener\SomeListener
    tags:
        - { name: kernel.event_listener, event: kernel.terminate, method: onKernelTerminate }

听众:

<?php

namespace SomeBundle\EventListener;

use Symfony\Component\HttpKernel\Event\PostResponseEvent;

class SomeListener
{
    public function onKernelTerminate(PostResponseEvent $event)
    {
        // provide time consuming tasks here
    }
}
于 2016-01-21T11:03:25.463 回答
0

不是最好的解决方案,但是:

$process = new Process('nohup php subscript.php &');
$process->start();
于 2016-01-20T16:01:27.610 回答