Как настроить асинхронные задачи в PHP?php-52

PHP изначально синхронный и однопоточный, но асинхронные задачи можно реализовать несколькими способами. Рассмотрим популярные подходы.

1. Очереди сообщений

Самый надежный способ для фоновых задач. Популярные брокеры:

RabbitMQ

Пример с библиотекой php-amqplib:

<?php
require_once __DIR__ . '/vendor/autoload.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('Hello World!');
$channel->basic_publish($msg, '', 'task_queue');

$channel->close();
$connection->close();

Redis

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->rPush('task_queue', json_encode(['task' => 'send_email']));

2. Системные демоны

Запуск PHP-скриптов как демонов:

#!/usr/bin/env php
<?php
while (true) {
    // Проверяем наличие задач
    $task = getTaskFromQueue();
    if ($task) {
        processTask($task);
    }
    sleep(1);
}

Запуск: nohup php worker.php > /dev/null 2>&1 &

3. ReactPHP/Amp

Библиотеки для асинхронного программирования:

<?php
require 'vendor/autoload.php';

$loop = React\EventLoop\Factory::create();

$loop->addTimer(1, function () {
    echo "Асинхронная задача выполнена!\n";
});

$loop->run();

4. Готовые решения

  • Symfony Messenger: Встроенная система очередей
  • Laravel Queues: Драйверы для Redis, SQS, Beanstalkd
  • Gearman: Распределенная система задач

5. CRON для периодических задач

Пример cron-задачи:

* * * * * /usr/bin/php /path/to/script.php

Критерии выбора подхода

Критерий Очереди Демоны ReactPHP CRON
Сложность Средняя Низкая Высокая Низкая
Надежность Высокая Средняя Низкая Средняя
Масштабируемость Высокая Низкая Средняя Низкая

Резюмируем:

Для production-решений лучше использовать очереди (RabbitMQ/Redis). Для простых задач подойдут демоны или CRON. ReactPHP/Amp — для сложных асинхронных сценариев.