PHP异步编程:完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

PHP 异步编程简介

传统上,PHP 被认为是一种同步语言:每个请求按顺序执行,在输入输出操作(例如读取文件或数据库查询)完成之前会阻塞执行。然而,随着高负载 Web 应用和微服务的日益流行,需要在不扩展进程数量的情况下处理数万个并发连接。异步编程通过允许在单个线程内并发执行操作来解决这个问题。

在本教程中,我们将分析 PHP 中异步的工作原理、可用的工具以及如何正确构建非阻塞应用程序。您将了解生成器、协程、ReactPHP、Amp 和 Swoole 库,以及新的 Fibers 扩展。

异步基础:Event Loop 和非阻塞输入输出

异步编程基于 Event Loop(事件循环)的概念。这是一个无限循环,等待并处理事件:网络请求、输入输出操作完成、定时器。代码不是等待操作完成,而是注册一个回调(callback),当数据准备好时执行该回调。这样可以避免浪费 CPU 时间等待。

PHP 传统上使用阻塞函数(例如 file_get_contents()sleep())。为了异步工作,需要用非阻塞的替代品替换它们。以下是一个使用 ReactPHP 库的简单示例:

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

use React\\EventLoop\\Factory;
use React\\Promise\\Promise;

$loop = Factory::create();

// 异步读取文件
$promise = new Promise(function ($resolve, $reject) use ($loop) {
    $loop->addTimer(0.001, function () use ($resolve) {
        $content = file_get_contents('/etc/hosts');
        $resolve($content);
    });
});

$promise->then(function ($data) {
    echo "已读取: " . strlen($data) . " 字节";
});

echo "此代码将立即执行,无需等待文件读取";
$loop->run();
?>

在此示例中,addTimer 注册了一个将在循环的下一个 tick 中执行的任务。Event Loop 不会被阻塞,我们立即看到消息,而读取结果稍后出现。

生成器和协程:控制执行流程

生成器(yield)出现在 PHP 5.5 中,允许暂停函数执行并返回中间值。在此基础上构建了 协程——轻量级线程,可以自愿交出控制权。与 Event Loop 结合,生成器允许编写看起来像同步但异步执行的代码。

考虑一个使用 Amp 库的示例,该库使用协程:

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

use Amp\\Loop;
use Amp\\Delayed;

// 异步协程
$coroutine = function () {
    echo "协程开始";
    // 暂停 1 秒而不阻塞
    yield new Delayed(1000);
    echo "已过 1 秒";
    yield new Delayed(500);
    echo "又过了 0.5 秒";
};

Loop::run(function () use ($coroutine) {
    // 启动协程
    $result = yield from $coroutine();
    echo "协程已完成";
});
?>

在此代码中,yield new Delayed(1000) 暂停协程的执行,将控制权交还给 Event Loop。1 秒后,执行从同一位置恢复。这使得可以同时处理数千个这样的协程,而无需创建新进程。

用于异步 PHP 的库和工具

在 PHP 中处理异步有多个成熟的库。让我们看看三个最流行的。

ReactPHP

ReactPHP 是最古老且最知名的库。它提供 Event Loop、Promise(类似于 JavaS

博客

书籍推荐