Swoole 是什么?
Swoole
是一个使用 C++
语言编写的基于异步事件驱动和协程的并行网络通信引擎,为PHP
提供协程
、高性能
网络编程支持。提供了多种通信协议的网络服务器和客户端模块,可以方便快速的实现TCP/UDP服务
、高性能Web
、WebSocket服务
、物联网
、实时通讯
、游戏
、微服务
等,使PHP
不再局限于传统的Web领域。
Swoole 扩展安装
Swoole
扩展是按照PHP
标准扩展构建的。使用phpize
来生成编译检测脚本,./configure
来做编译配置检测,make
进行编译,make install
进行安装。
PHP官方安装包地址:https://pecl.php.net/package/swoole
下载最新版本
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
,是一种比线程更加轻量级的存在。最重要的是,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)。
协程不是进程或线程,其执行过程更类似于子进程,或者说不带返回值的函数调用。一个程序可以包含多个协程,可以对比与一个进程包含多个线程,因而下面我们来比较协程和线程。而多个线程相对独立,有自己的上下文,切换受系统控制;而协程也相对独立,有自己的上下文,但是其切换由自己控制,由当前协程切换到其他协程由当前协程来控制。
协程执行顺序
图片来源:easyswoole 官网
小万的一天
场景:小万烧开水需要
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
完成再继续执行之前的代码.