Swoole 是什么?

Swoole 是一个使用 C++ 语言编写的基于异步事件驱动和协程的并行网络通信引擎,为PHP提供协程高性能网络编程支持。提供了多种通信协议的网络服务器和客户端模块,可以方便快速的实现TCP/UDP服务高性能WebWebSocket服务物联网实时通讯游戏微服务等,使PHP不再局限于传统的Web领域。

Swoole 扩展安装

Swoole扩展是按照PHP标准扩展构建的。使用phpize来生成编译检测脚本,./configure来做编译配置检测,make进行编译,make install进行安装。

PHP官方安装包地址:https://pecl.php.net/package/swooleopen in new window

下载最新版本

wget https://pecl.php.net/get/swoole-5.1.1.tgz

解压

tar -zxvf swoole-5.1.1.tgz

生成 ./configure 配置文件

cd swoole-5.1.1/

/usr/local/php-8.2.14/bin/phpize 

Configuring for:
PHP Api Version:         20220829
Zend Module Api No:      20220829
Zend Extension Api No:   420220829

指定配置文件

./configure --with-php-config=/usr/local/php-8.2.14/bin/php-config

编译安装

$ make
$ sudo make install

Installing shared extensions:     /usr/local/php-8.2.14/lib/php/extensions/no-debug-non-zts-20220829/
Installing header files:          /usr/local/php-8.2.14/include/php/

php.ini 添加扩展 swoole.so

sudo vim /usr/local/php-8.2.14/etc/php.ini

extension=swoole.so

命令行检查是否安装成功

/usr/local/php-8.2.14/bin/php -m |grep swoole
swoole

webman开启swoole事件驱动

webman框架中开启swoole事件驱动特别简单,只有配置一下就可以了。

修改配置文件config/server.php服务配置文件

return [
    'listen'           => 'http://0.0.0.0:8787',
    'transport'        => 'tcp',
    'context'          => [],
    'name'             => 'webman',
    'count'            => cpu_count() * 10,
    'user'             => '',
    'group'            => '',
    'reusePort'        => false,
    'event_loop'       => Workerman\Events\Swoole::class,
    'stop_timeout'     => 2,
    'pid_file'         => runtime_path() . '/webman.pid',
    'status_file'      => runtime_path() . '/webman.status',
    'stdout_file'      => runtime_path() . '/logs/stdout.log',
    'log_file'         => runtime_path() . '/logs/workerman.log',
    'max_package_size' => 10 * 1024 * 1024
];

没错,'event_loop' => Workerman\Events\Swoole::class,就这么一句解决。

启动webman,查看事件驱动是否已经是swoole事件驱动

/usr/local/php-8.2.14/bin/php start.php start

Workerman[start.php] start in DEBUG mode
----------- WORKERMAN --------------------------------------------
Workerman version:4.1.14          PHP version:8.2.14           Event-Loop:Workerman\Events\Swoole
----------- WORKERS ---------------------------------------------
proto   user            worker          listen                 processes    status           
tcp     www             webman          http://0.0.0.0:8888    8             [OK]            
tcp     www             monitor         none                   1             [OK]            
-----------------------------------------------------------------

查看运行状态/usr/local/php-8.2.14/bin/php start.php status

推荐安装 IDE Helper

composer require --dev swoole/ide-helper:@dev

协程

协程,英文Coroutines,是一种比线程更加轻量级的存在。最重要的是,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)

协程不是进程或线程,其执行过程更类似于子进程,或者说不带返回值的函数调用。一个程序可以包含多个协程,可以对比与一个进程包含多个线程,因而下面我们来比较协程和线程。而多个线程相对独立,有自己的上下文,切换受系统控制;而协程也相对独立,有自己的上下文,但是其切换由自己控制,由当前协程切换到其他协程由当前协程来控制。

协程执行顺序

图片来源:easyswooleopen in new window 官网

小万的一天

场景:小万烧开水需要10秒钟,洗脸需要3秒钟,吃早餐需要5秒钟,请问做完这些事情总共需要几秒钟?

答案是:10秒钟。因为在烧开水这个步骤时,不需要坐在那里看水壶烧(异步,io耗时)可以先去洗脸,然后去吃早餐。

协程伪代码go.php

<?php

/** 第一个协程 */
go(function () {
    /** 模拟IO等待10秒 */
    \Co::sleep(10);
    echo '[x] [任务1]  小万烧开水需要:[10s] ' . date('Y-m-d H:i:s') . PHP_EOL;
    echo '[x] [主任务] 小万的一天结束:[0s] ' . date('Y-m-d H:i:s') . PHP_EOL;
});

/** 第二个协程 */
go(function () {
    /** 模拟IO等待3秒 */
    \Co::sleep(3);
    echo '[x] [任务2]  小万洗完脸需要:[3s] ' . date('Y-m-d H:i:s') . PHP_EOL;
});

/** 第三个协程 */
go(function () {
    /** 模拟IO等待5秒 */
    \Co::sleep(5);
    echo '[x] [任务3]  小万吃早餐需要:[5s] ' . date('Y-m-d H:i:s') . PHP_EOL;
});

echo '[x] [主任务] 小万的一天开始:[0s] ' . date('Y-m-d H:i:s') . PHP_EOL;

协程伪代码执行结果

[x] [主任务] 小万的一天开始:[0s] 2024-01-20 05:40:03
[x] [任务2]  小万洗完脸需要:[3s] 2024-01-20 05:40:06
[x] [任务3]  小万吃早餐需要:[5s] 2024-01-20 05:40:08
[x] [任务1]  小万烧开水需要:[10s] 2024-01-20 05:40:13
[x] [主任务] 小万的一天结束:[0s] 2024-01-20 05:40:13

协程的运行是交叉式运行(串行)。协程的优点主要在于这里,当遇上io耗时的情况时,这部分的等待时间其实可以节约出来,去先处理其他代码逻辑的,直到io完成再继续执行之前的代码.

Last Updated:
贡献者: Tinywan