开源技术小栈开源技术小栈
🌐 Home
⛄ 精选文章
🐜 数据库
Ⓜ️ 微服务
📺 Bilibili
🐳 Github
🎃 腾讯云社区
💫 博客园
  • 💫 Git
  • 🐜 Linux
  • 🕸️ Docker
  • 🐌 Jenkins
🌐 Home
⛄ 精选文章
🐜 数据库
Ⓜ️ 微服务
📺 Bilibili
🐳 Github
🎃 腾讯云社区
💫 博客园
  • 💫 Git
  • 🐜 Linux
  • 🕸️ Docker
  • 🐌 Jenkins
  • 0X01 2025

    • 🔶 大模型编程0X01 | 调用 API 完成内容分类
    • 🔶 PHP8.5 新增管道操作符
    • 🔶 Redis搭建高并发电商秒杀系统
    • 🔶 MQTT与PHP使用实时消息传递指南
    • 🔶 MQTT消息协议初学者指南
  • 0X01 2024

    • 🔷 SaaS多租户架构数据源动态切换解决方案
    • 🔶 HTTP分块Chunk传输让客户端响应更迅速数据
    • 🔷 PHP使用JSONSchema进行API模式验证和类型检查
    • 🔶 PHP日志管理神器Monolog
    • 🔷 使用PHP创建和管理自己的JWT令牌
    • 🔶 谁说PHP不能异步和并行运行?
    • 🔷 webman使用RabbitMQ消息中间件实现系统异步解耦实战教程
    • 🔶 基于Websocket和Canvas实现多人协作实时共享白板
    • 🔶 PHP高性能纯协程网络通信引擎Swow
    • 🔶 webman如何使用swoole事件驱动和协程?
    • 🔶 高性能PHP框架webman协程插件入门实战
    • 🔶 编译PHP 8.3并快速启动ThinkPHP 8.0框架项目
    • 🔶 【转载】漫谈Swoole协程与异步IO

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完成再继续执行之前的代码.

最近更新: 2024/9/28 06:39
贡献者: Tinywan
Prev
🔶 PHP高性能纯协程网络通信引擎Swow
Next
🔶 高性能PHP框架webman协程插件入门实战