拍h片的朋友们,来吧,今天在推广下php优秀开源生态项目workerman,workman官方在新年的第一天发布了5.0版本,就让我们来看看更新了啥!
关于workerman
workerman是一款开源高性能PHP应用容器,它大大突破了传统PHP应用范围,被广泛的用于互联网、即时通讯、APP开发、硬件通讯、智能家居、物联网等领域的开发。这个项目在GitHub上目前star:11.2k, 妥妥的明星项目。
v5版本
作者说:“v5 的发布标志着性能与稳定性的进一步提升,协程的引入也为开发者们带来了更多可能性。未来,我们将继续携手,共同推动 Workerman 的发展,为更多开发者提供强大的工具与支持。”
主要特性
协程化
workerman取大家之所长,集成了fiber、swoole、swow。
- 支持Fiber协程
- 支持Swoole协程
- 支持Swow协程
注意
同一个Worker中Fiber协程、Swoole协程、Swow协程无法共存,只能使用其中一种。
不同Worker可以设置不同的协程驱动类型
Fiber协程
composer require revolt/event-loop ^1.0.0
eventLoop = Revolt::class;
$worker->onMessage = function (TcpConnection $connection, Request $request) {
$connection->send('hello workerman');
};
Worker::runAll();
Swoole协程
安装Swoole
测试代码
eventLoop = Swoole::class;
$worker->onMessage = function (TcpConnection $connection, Request $request) {
$connection->send('hello workerman');
};
Worker::runAll();
Swow协程
安装Swow
测试代码
eventLoop = Swow::class;
$worker->onMessage = function (TcpConnection $connection, Request $request) {
$connection->send('hello workerman');
};
Worker::runAll();
不兼容的变更
websocket协议onWebSocketConnect事件
$worker = new Worker('websocket://0.0.0.0:2345');
$worker->onWebSocketConnect = function (TcpConnection $connection, Request $request) {
// 不再支持 $_GET $_SERVER 获取参数,统一使用$request获取参数
$token = $request->get('token');
};
新增接口
- Timer::public static function repeat($time, $callback, $args) 一次性定时器
相当于 Timer::add($time, $callback, $args, false) - Timer::repeat($time, $callback, $args) 连续性定时器
相当于 Timer::add($time, $callback, $args)
协程优点
PHP引入协程后最大的作用就是可以用同步的方式编写异步代码,避免了回调地狱,提高了代码的可读性和可维护性。
引入协程后可以让应用有更好的弹性,尤其在慢IO的情况下,能大幅提升应用性能。
协程缺点
但是引入协程后开发者需要时刻注意全局变量污染、资源竞争、第三方库改造等问题,开发维护成本增大,心智负担明显增加。
引入协程后产生了协程创建、调度、销毁、连接池等额外开销。
不管通过swoole自己的压测还是workerman的压测,在充分利用资源的情况下,引入协程后性能比阻塞式IO,MySQL单查询极限性能下降约5%-15%左右,PgSQL单查询性能下降更多。
尽管使用协程极限性能会下降,但是协程在慢IO的业务下会大幅度提高吞吐率。
来自作者walkor的交流
知识总结-协程
协程(Coroutine)是一种轻量级的线程,它允许在单个线程中执行多个任务,并能在任务之间切换而不需要线程切换的开销。协程通过合作式调度来管理任务的执行顺序,避免了传统多线程中的上下文切换(不依赖操作系统调度)。它通常在异步编程中使用,以便在等待 I/O 操作时不会阻塞主线程,从而提高效率。
比喻:协程像一个“多任务的厨师”
想象你是一名厨师,正在准备一顿大餐。你的工作中有多个任务,比如切菜、煮汤、翻煎饼、准备沙拉等。你不能同时做所有事情,但你可以在每项任务的“空闲时间”切换到下一个任务,避免浪费时间等待。
- 传统的单任务厨师:只做一件事,等一件事做完才能开始下一件事。
- 多任务的厨师(协程):做一会儿煎饼,等它煎好时去切菜,煎饼好了再回来翻,类似这种在不同任务间“切换”。这个切换不是通过“暂停和重启厨房”,而是在当前任务暂时不需要操作时灵活切换到下一个任务。
这就类似协程:在一个线程中,我们可以在不同的任务之间进行切换,不需要创建多个线程或进程。
协程的执行过程
- 开始切菜:厨师开始切菜(任务A)。
- 煮汤开始:厨师开始做第二个任务——煮汤(任务B)。
- 等待水烧开:煮汤任务进入等待状态。
- 继续切菜:厨师返回切菜任务(切菜任务在等待时被挂起,执行其他任务)。
- 做沙拉开始:厨师开始做沙拉(任务C)。
- 准备沙拉材料:做沙拉任务进入准备阶段。
- 继续切菜:厨师再次返回切菜任务,继续执行。
- 水烧开,继续煮汤:水烧开后,煮汤任务继续执行。
- 完成切菜,开始翻煎饼:切菜完成后,厨师继续翻煎饼(新的任务)。
- 完成所有任务,结束:所有任务完成,厨师的工作结束
协程的执行时序图:
协程与进程、线程的对比
特性 | 进程 | 线程 | 协程 |
内存独立性 | 每个进程有独立的内存空间,彼此隔离 | 同一进程中的线程共享内存空间 | 协程通常在同一线程中运行,共享内存 |
创建与销毁开销 | 创建和销毁进程的开销较大 | 创建和销毁线程的开销较大 | 协程的创建和销毁开销很小 |
调度方式 | 操作系统调度,不同进程间的切换有较高开销 | 操作系统调度,同一进程的线程切换较轻 | 用户控制调度,协程切换几乎无开销 |
并发性 | 每个进程独立运行,可以并行执行 | 线程在进程中并行执行 | 单线程并发,任务切换通过协程管理 |
通信 | 进程间通信需要专门的机制(如管道、共享内存等) | 线程间通信较简单,通过共享内存即可 | 协程通过函数调用、yield 或 suspend 实现任务间协作 |
上下文切换 | 进程切换较重,需要操作系统管理,包含完整的上下文保存和恢复 | 线程切换有一定的开销,操作系统管理 | 协程切换非常轻量级,由应用程序控制,几乎没有上下文切换开销 |
适用场景 | 适用于独立任务的并行执行,高资源消耗的任务 | 适用于需要高并发的场景,尤其是计算密集型任务 | 适用于 I/O 密集型的并发任务,减少阻塞,提高资源利用率 |
PHP 的 Fibers 协程
PHP 8.1 引入了 Fiber,它为 PHP 提供了协程支持。Fibers 是一种低级的协程机制,允许你在 PHP 中手动控制执行的暂停和恢复。Fibers 本质上是 PHP 中的一种协作式多任务机制,可以在单个请求中调度多个任务,使得异步操作不再依赖于事件循环。
PHP Fiber 的好处:
- 减少阻塞:
- 传统的同步代码往往会在等待 I/O 操作时阻塞程序,导致性能瓶颈。而通过协程,任务可以在等待 I/O 操作时挂起,允许其他任务执行,从而提高并发性和资源利用率。
- 更简单的异步编程模型:
- 使用 Fiber,开发者可以像写同步代码一样编写异步代码,避免了回调地狱(callback hell)的问题。这使得代码结构更清晰,易于理解和维护。
- 无需额外的线程开销:
- 传统的多线程并发模型需要操作系统的线程调度,带来了较高的开销。而协程通过单线程的协作式调度,大大减少了上下文切换的开销。
- 易于控制的执行流程:
- 使用 Fiber,开发者可以精确地控制代码执行的暂停和恢复时机,这对于某些需要精细调度的应用非常有用。例如,在某些 IO 密集型应用中,能在合适的时机暂停任务,等待 I/O 操作完成,然后再恢复执行。
- 无需全局事件循环:
- PHP 的协程机制不需要像 Node.js 那样使用事件循环。通过 Fiber,可以在同步代码中嵌入异步逻辑,而不必依赖复杂的事件驱动架构。
- 提高并发性:
- Fiber 允许在多个任务之间快速切换,这使得在 PHP 中实现并发执行变得更加高效。例如,在高并发情况下,PHP 可以通过 Fiber 挂起当前任务,让其他任务继续执行,从而提高系统的整体吞吐量。
$fiber = new Fiber(function (): void {
echo "Start\n";
Fiber::suspend(); // 挂起当前 Fiber
echo "Resumed\n";
});
echo "Before Fiber\n";
$fiber->start(); // 启动 Fiber
echo "After Fiber Suspend\n";
$fiber->resume(); // 恢复 Fiber
echo "End\n";
总结
最后祝愿:workerman、swoole、swow能走更远。