PHP 怎么投递异步任务

wen PHP项目 1

本文目录导读:

PHP 怎么投递异步任务

  1. 使用消息队列(推荐)
  2. 使用进程管理工具
  3. 使用 Swoole 异步任务
  4. 使用 HTTP 异步请求
  5. 使用 Supervisor 常驻进程
  6. 使用现成的任务队列库
  7. 选择建议
  8. 最佳实践建议

在 PHP 中投递异步任务有以下几种常见方式,我为你详细介绍:

使用消息队列(推荐)

Redis 队列

<?php
// 投递任务
use Predis\Client;
$redis = new Client();
$taskData = json_encode([
    'type' => 'send_email',
    'data' => ['to' => 'user@example.com', 'content' => 'Hello']
]);
// 推入队列
$redis->rpush('task_queue', $taskData);
// 消费端(worker.php)
while (true) {
    $task = $redis->lpop('task_queue');
    if ($task) {
        $taskData = json_decode($task, true);
        // 处理任务
        handleTask($taskData);
    }
    usleep(100000); // 100ms延迟
}

RabbitMQ

<?php
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('task_queue', false, true, false, false);
$msg = new AMQPMessage(json_encode($taskData), [
    'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT
]);
$channel->basic_publish($msg, '', 'task_queue');

使用进程管理工具

Gearman

<?php
$client = new GearmanClient();
$client->addServer('localhost', 4730);
// 异步投递任务
$client->doBackground('send_email', json_encode($taskData));
// 处理端(Worker)
$worker = new GearmanWorker();
$worker->addServer('localhost', 4730);
$worker->addFunction('send_email', function($job) {
    $data = json_decode($job->workload(), true);
    // 处理任务
});

使用 Swoole 异步任务

<?php
$server = new Swoole\Server('127.0.0.1', 9501);
$server->set([
    'task_worker_num' => 4,
    'worker_num' => 2
]);
// 投递任务
$server->on('Receive', function($server, $fd, $reactor_id, $data) {
    $taskData = [
        'type' => 'send_email',
        'data' => json_decode($data, true)
    ];
    $server->task($taskData);
});
// 处理异步任务
$server->on('Task', function($server, $task_id, $worker_id, $taskData) {
    handleTask($taskData);
    $server->finish("Task completed");
});
// 任务完成回调
$server->on('Finish', function($server, $task_id, $data) {
    echo "Task $task_id completed: $data\n";
});

使用 HTTP 异步请求

使用 curl 异步(非阻塞)

<?php
function asyncRequest($url, $params = []) {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($params),
        CURLOPT_TIMEOUT => 1, // 1秒超时
        CURLOPT_FRESH_CONNECT => true,
        CURLOPT_TIMEOUT_MS => 1000,
    ]);
    // 异步执行,不等待响应
    curl_exec($ch);
    curl_close($ch);
}

使用 Guzzle 异步客户端

<?php
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client(['base_uri' => 'http://localhost:8000']);
// 异步请求
$promise = $client->postAsync('/handle-task', [
    'json' => $taskData
]);
$promise->then(
    function($response) {
        echo "Task completed: " . $response->getBody();
    },
    function($exception) {
        echo "Task failed: " . $exception->getMessage();
    }
);
$promise->wait();

使用 Supervisor 常驻进程

创建 Worker 脚本并配置 Supervisor 管理:

<?php
// worker.php
while (true) {
    $task = getNextTask(); // 从队列获取任务
    if ($task) {
        try {
            handleTask($task);
            markTaskCompleted($task);
        } catch (Exception $e) {
            error_log($e->getMessage());
            retryTask($task);
        }
    }
    sleep(1);
}

使用现成的任务队列库

Laravel Queue

<?php
// 投递任务
use App\Jobs\SendEmail;
use Illuminate\Support\Facades\Queue;
Queue::push(new SendEmail($user, $content));
// 或者延迟执行
Queue::later(now()->addMinutes(10), new SendEmail($user, $content));

Beanstalkd

<?php
use Pheanstalk\Pheanstalk;
$pheanstalk = Pheanstalk::create('127.0.0.1');
$pheanstalk
    ->useTube('email_tasks')
    ->put(json_encode($taskData));
// 消费端
while ($job = $pheanstalk->watch('email_tasks')->reserve()) {
    $data = json_decode($job->getData(), true);
    handleTask($data);
    $pheanstalk->delete($job);
}

选择建议

方案 适用场景 优点 缺点
Redis队列 中小型项目 简单易用,性能好 可能丢失数据
RabbitMQ 企业级应用 可靠,功能强大 部署复杂
Swoole 高性能场景 性能最好 需要Swoole扩展
Gearman 分布式任务 跨语言支持 较老的技术
Laravel Queue Laravel项目 集成度高 依赖框架
HTTP请求 简单任务 实现简单 不可靠

最佳实践建议

  1. 可靠性要求高:使用 RabbitMQ + Supervisor
  2. 性能要求高:使用 Swoole Task Worker
  3. 简单快速实现:使用 Redis 队列
  4. 已有框架:优先使用框架自带的任务系统

选择哪种方案取决于你的具体需求,包括数据可靠性、性能要求、系统复杂度等因素。

抱歉,评论功能暂时关闭!