К основному содержимому

Fibers в PHP: асинхронный код без расширений

PHP · 18.10.2026 · 3 мин чтения
Иллюстрация к статье «Fibers в PHP: асинхронный код без расширений»

Fiber (PHP 8.1+) — это встроенный в язык механизм приостановки и возобновления выполнения функции без расширений вроде Swoole. Сам по себе Fiber не даёт параллелизма или неблокирующего I/O — он только управляет точкой возврата, а сетевые и файловые операции без блокировки сверху добавляют библиотеки планировщика, такие как Revolt или amphp.

Что Fiber делает, а что нет

Fiber оборачивает функцию в объект, который можно запустить, приостановить изнутри и возобновить снаружи, передавая значения в обе стороны. Это низкоуровневый примитив — переключение контекста без создания нового процесса или потока ОС, в пределах одного процесса PHP.

Fiber сам не делает сетевой вызов неблокирующим: без цикла событий вокруг него suspend просто останавливает выполнение до явного resume. Именно такой цикл событий (Revolt, amphp) превращает набор Fiber в реальный асинхронный код с несколькими задачами одновременно.

Минимальный пример: start, suspend, resume

Ниже — буквально вся механика Fiber без библиотек планировщика: функция приостанавливается внутри, а код снаружи решает, когда её возобновить и что передать обратно.

$fiber = new Fiber(function (): void {
    $value = Fiber::suspend('started');
    echo $value, PHP_EOL;
});
$fiber->start();
$fiber->resume('resumed');

Чем это отличается от корутин Swoole

Swoole даёт готовый цикл событий, неблокирующий ввод-вывод на уровне расширения и собственный HTTP-сервер — всё это разобрано в статье про Swoole и RoadRunner. Fiber — это только базовый кирпич языка, на котором библиотеки уровня Revolt строят такой же цикл событий без C-расширения, жертвуя частью производительности ради переносимости на любой хостинг с PHP 8.1 и выше.

  • Нужна обёртка-планировщик (Revolt, amphp) — без неё Fiber не даёт конкурентности
  • Нет встроенного неблокирующего клиента для MySQL или Redis, как в Swoole
  • Работает в любом окружении CLI и FPM без установки расширения
  • Переключение между Fiber дешевле создания потока, но дороже вызова обычной функции
  • Исключения внутри Fiber нужно явно перехватывать при resume, иначе они теряются

Где Fiber действительно полезен на практике

Fiber годится там, где скрипт выполняет несколько независимых операций ожидания — несколько HTTP-запросов к внешним API, несколько запросов к очереди — и запущен в обычном PHP-процессе CLI, а не под Swoole. Разница между запуском через CLI и через FPM для таких длительных скриптов разобрана в статье про PHP в cron.

Fiber не заменяет очередь сообщений: он ускоряет ожидание внутри одного процесса, но не даёт изоляции от падения процесса и не перезапускает задачу сам. Надёжный перезапуск воркеров очередей через Supervisor остаётся отдельной темой, разобранной в статье про очереди PHP и Supervisor.

Таблица: подходы к конкурентности в PHP

Таблица сравнивает механизмы, а не скорость — конкретная разница в производительности зависит от задачи и должна быть измерена отдельно.

ПодходНужно расширениеТипичная задача
Обычный блокирующий PHPнетпростой скрипт, одна задача за раз
Fiber + Revolt или amphpнетнесколько независимых HTTP-запросов в CLI-скрипте
Swooleдадолгоживущий сервер с корутинами и своим HTTP-сервером
RoadRunnerнет, отдельный бинарникдолгоживущие PHP-воркеры за Go-сервером

Частые вопросы

Нужно ли менять код на Fiber ради ускорения обычного сайта?

Нет: если сайт обслуживается через PHP-FPM с одним запросом на процесс, Fiber ничего не ускоряет без цикла событий вокруг него и без перехода на долгоживущие воркеры.

Можно ли использовать Fiber вместе с Swoole?

Да, Swoole сам построен на похожей идее переключения контекста и предоставляет собственные корутины, которые во многих версиях совместимы с кодом на Revolt внутри одного процесса.

Что происходит с исключением внутри Fiber, если его не перехватить?

Исключение всплывает при следующем вызове resume на этом Fiber, а не в момент выброса внутри функции — если вызывающий код не оборачивает resume в try-catch, исключение прерывает выполнение так же, как обычное необработанное исключение.

Статья помогла?
← Назад в базу знаний Задать вопрос поддержке