本文目录导读:

在 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请求 | 简单任务 | 实现简单 | 不可靠 |
最佳实践建议
- 可靠性要求高:使用 RabbitMQ + Supervisor
- 性能要求高:使用 Swoole Task Worker
- 简单快速实现:使用 Redis 队列
- 已有框架:优先使用框架自带的任务系统
选择哪种方案取决于你的具体需求,包括数据可靠性、性能要求、系统复杂度等因素。