高性能PHP框架webman協(xié)程Redis動(dòng)態(tài)連接池
?? 簡(jiǎn)介
webman-coroutine 是一個(gè) webman 開發(fā)框架生態(tài)下的協(xié)程基建支撐插件
?? 起源
- workerman 4.x 及基于其作為運(yùn)行容器的 webman 框架不支持協(xié)程
- workerman 5.x 及基于其作為運(yùn)行容器的 webman 框架不具備完備的協(xié)程能力
- workerman / webman 沒有一個(gè)較為統(tǒng)一的協(xié)程使用方式,導(dǎo)致切換協(xié)程驅(qū)動(dòng)的開發(fā)成本較高,試錯(cuò)成本較高
- 自行實(shí)現(xiàn)協(xié)程版worker、server開發(fā)成本較高,試錯(cuò)成本較高
??? 目的
- 提供 workerman/webman 多樣的基礎(chǔ)協(xié)程事件庫(kù),兼容支持workerman 4.x和workerman 5.x的協(xié)程驅(qū)動(dòng)
revolt/PHP-fiber
swow
swoole
ripple
- 提供 workerman/webman 統(tǒng)一的協(xié)程開發(fā)工具,兼容非協(xié)程環(huán)境
- 協(xié)程通道:Utils/Channel
- 協(xié)程等待:Utils/WaitGroup
- 協(xié)程:Utils/Coroutine
- 協(xié)程化Worker:Utils/Worker
- 對(duì)象池:Utils/Pool
?? 愿景
- 在 workerman/webman 開發(fā)環(huán)境下,提供一套簡(jiǎn)單的協(xié)程工具包,降低認(rèn)知負(fù)荷。
- 在 workerman/webman 開發(fā)環(huán)境下,嘗試實(shí)現(xiàn)一套兼容協(xié)程與非協(xié)程開發(fā)的方案,讓選擇和擺脫方案更簡(jiǎn)單,避免更多的焦慮。
- 在 workerman/webman 開發(fā)環(huán)境下,盡可能實(shí)現(xiàn)對(duì)官方組件的無(wú)侵入式協(xié)程化改造(雖然很難,但也想試試)。
- 希望在代碼的實(shí)現(xiàn)上能夠給更多PHP開發(fā)帶來(lái)一些幫助,甚至靈感。
?? 安裝
通過(guò)composer安裝
composer require workbunny/webman-coroutine
安裝日志
# composer require workbunny/webman-coroutine
./composer.json has been updated
Running composer update workbunny/webman-coroutine
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 1 update, 0 removals
- Upgrading workbunny/webman-coroutine (1.1.4 => 1.2.1)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 4 installs, 0 updates, 1 removal
- Downloading tinywan/exception-handler (v1.5.4)
- Downloading workbunny/webman-coroutine (1.2.1)
> support\Plugin::uninstall
- Removing openspout/openspout (v4.26.0)
- Installing composer/semver (3.4.3): Extracting archive
- Installing swow/swow (v1.5.3): Extracting archive
- Installing tinywan/exception-handler (v1.5.4): Extracting archive
- Installing workbunny/webman-coroutine (1.2.1): Extracting archive
> support\Plugin::install
> support\Plugin::install
> support\Plugin::install
> support\Plugin::install
Create config/plugin/workbunny/webman-coroutine
Generating autoload files
55 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
Using version ^1.2 for workbunny/webman-coroutine
??安裝 swow
通過(guò)composer安裝
composer require swow/swow
使用./vendor/bin/swow-builder安裝swow拓展
vendor/bin/swow-builder --rebuild --install
> cd /var/www/demo.webman.tinywan.com/vendor/swow/swow/ext && \
phpize --clean
Cleaning..
? Clean done
> cd /var/www/demo.webman.tinywan.com/vendor/swow/swow/ext && \
phpize && \
./configure
Configuring for:
PHP Api Version: 20230831
Zend Module Api No: 20230831
Zend Extension Api No: 420230831
checking for grep that handles long lines and -e... /bin/grep
Directive => Local Value => Master Value
swow.enable => On => On
swow.async_threads => 0 => 0
swow.async_file => On => On
swow.async_tty => On => On
> cd /var/www/demo.webman.tinywan.com/vendor/swow/swow/ext && \
make install
Installing shared extensions: /usr/local/lib/php/extensions/no-debug-non-zts-20230831/
? Install done
?????? All tasks have been completed ??????
?? webman 使用
1. 配置config/server.php
修改事件驅(qū)動(dòng)為event_loop(),event_loop()用于自動(dòng)判斷當(dāng)前環(huán)境適合的event loop和協(xié)程驅(qū)動(dòng)
'event_loop' => \Workbunny\WebmanCoroutine\event_loop(),
2. 占位初始化
在webman框架的控制器使用的時(shí)候,存在會(huì)被多次調(diào)用Pool::create()方法多次創(chuàng)建重復(fù)區(qū)域會(huì)拋出異常,可以在config/bootstrap.php中占位初始化。新增如下配置
<?php
return [
// 其他配置
\app\common\CoroutinePool::class
];
CoroutinePool.php協(xié)程連接池
<?php
/**
* @desc CoroutinePool.php 描述信息
* @author Tinywan(ShaoBo Wan)
*/
declare(strict_types=1);
namespace app\common;
use Webman\Bootstrap;
use Workbunny\WebmanCoroutine\Utils\Pool\Pool;
use Workerman\Worker;
class CoroutinePool implements Bootstrap
{
/***
* @desc start
* @param Worker|null $worker
* @author Tinywan(ShaoBo Wan)
*/
public static function start(?Worker $worker)
{
/** 為redis占位 */
Pool::init('redis',false);
}
}
3. 動(dòng)態(tài)池化
CoroutineController控制器偽代碼
<?php
/**
* @author Tinywan(ShaoBo Wan)
* @date 2024/10/17 23:37
*/
declare(strict_types=1);
namespace app\controller;
use Illuminate\Redis\Connections\Connection;
use support\Response;
use Workbunny\WebmanCoroutine\Utils\Pool\Pool;
class CoroutineController
{
/***
* @desc Redis 連接池
* @author Tinywan(ShaoBo Wan)
*/
public function pool(): Response
{
/** 獲取redis占位 */
$pools = Pool::get('redis', null);
/** 根據(jù)配置池大小判斷是否需要追加,假設(shè)你存在這樣的配置 */
if (count($pools) < config('redis.pool_size')) {
/** 新建redis連接 */
$config = config('redis');
$redis = new \Illuminate\Redis\RedisManager('', 'phpredis', $config);
/** 追加一個(gè)redis連接對(duì)象,資源類型不用clone */
Pool::append('redis', (int)array_key_last($pools) + 1, $redis, false);
}
$start = microtime(true);
/** 等待閑置redis */
$redis = Pool::waitForIdle('redis', function (Pool $pool): \Redis {
/** @var Connection $connection */
$connection = $pool->getElement();
/** 獲取redis連接 */
return $connection->client();
});
/** 執(zhí)行Redis命令 */
$res = $redis->lPush('webman:coroutine:key', '開源技術(shù)小棧' . date('Y-m-d H:i:s'));
$time = (string)(microtime(true) - $start);
return json(['time' => $time, 'res' => $res]);
}
}
4. 啟動(dòng)webman
通過(guò)以下命令啟動(dòng)webman
php -d extension=swow webman start
啟動(dòng)成功輸出
# php -d extension=swow webman start
Workerman[webman] start in DEBUG mode
---------------------------------------------------- WORKERMAN -----------------------------------------------------
Workerman version:4.1.15 PHP version:8.3.9 Event-Loop:Workbunny\WebmanCoroutine\Events\SwowEvent
----------------------------------------------------- WORKERS ------------------------------------------------------
proto user worker listen processes status
tcp root webman http://0.0.0.0:8217 8 [OK]
tcp root monitor none 1 [OK]
tcp root plugin.saiadmin.task none 1 [OK]
tcp root plugin.saiadmin.websocket websocket://0.0.0.0:9527 1 [OK]
--------------------------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
5. 請(qǐng)求訪問(wèn)
訪問(wèn)地址 http://127.0.0.1:8217/coroutine/pool
{
"time": "0.069719791412354",
"res": 1
}
Redis數(shù)據(jù)存儲(chǔ)結(jié)果
圖片