概述
在现代的互联网应用开发中,性能和实时性是衡量一个应用成功的关键指标。Workerman 和 Swoole 作为 PHP 社区中流行的高性能通信库,它们的结合使用为开发者提供了强大的异步网络通信能力。本文将深入探索如何利用 Workerman 5.0 结合 Swoole 5.0 来实现一键协程。
🥁 问:
workerman5.0
为什么要使用
swoole5.0
,原因很简单:
workerman5.0
全面支持Swoole驱动。更多了解:https://github.com/walkor/workerman/releases/tag/v5.0.0-beta.1
使用
强烈建议看看这个作为入门: 。
为了方便开发和部署,这里直接使用docker容器。
docker pull tinywan/docker-php-webman:8.2.17-swoole5.1
更多使用方法可以参考这里 https://github.com/Tinywan/docker-php-webman。该容器支持
swoole
扩展
5.1.1
# pecl info swoole
About pecl.php.net/swoole-5.1.1
===============================
Release Type PECL- style PHP extension (source code)
Name swoole
Channel pecl.php.net
Summary Event-driven asynchronous and concurrent
networking engine with high performance for PHP.
Description Event-driven asynchronous and concurrent
networking engine with high performance for PHP.
- event-driven
- coroutine
- asynchronous non-blocking
- multi-thread reactor
- multi-process worker
- multi-protocol
- millisecond timer
- built-in tcp/http/websocket/http2 server
- coroutine tcp/http/websocket client
- coroutine mysql client
- coroutine redis client
- coroutine read/write file system
- coroutine dns lookup
- support IPv4/IPv6/UnixSocket/TCP/UDP
- support SSL/TLS encrypted transmission
Maintainers Tianfeng Han <rango@swoole.com> (lead)
Twosee <twosee@php.net> (developer)
Shen Zhe <shenzhe163@gmail.com> (developer,
inactive)
Lu Fei <lufei@php.net> (developer)
Bruce Dou <doubaokun@php.net> (developer)
Release Date2023-11-2614:25:25
Release Version 5.1.1 (stable)
API Version 5.0 (stable)
License Apache2.0
(http://www.apache.org/licenses/LICENSE-2.0.html)
Release Notes - Fixed memory leak issue in HTTP coroutine
client
- Fixed the issue of can not hook pdo_odbc
- Fixed the error in executing
socket_import_stream()
- Fixed the issue with
Context::parse_multipart_data() unable to handle
empty request body
- Fixed the issue with PostgreSQL coroutine
client where the parameters are not working
- Fixed the bug where curl crashes during
destruction
- Fixed the compatibility issue between Swoole
5.x and the latest version of xdebug
- Fixed the problem of class not found error
caused by coroutine switching during the process
of class autoloading
- Fixed the issue of not being able to compile
Swoole on OpenBSD
Required Dependencies PHP version 8.0.0
PEAR installer version 1.4.0 or newer
package.xml version 2.0
Last Modified 2024-04-2110:05
Previous Installed - None -
Version
开启swoole事件驱动
在
webman
框架中开启
swoole
事件驱动特别简单,只有配置一下就可以了。修改配置文件
config/server.php
服务配置文件
'event_loop' => Workerman\Events\Swoole:: class
Docker 启动webman
$ docker run --rm -it -p 8887:8787 -v d:/dnmp/www/webman2024:/app tinywan/docker-php-webman:8.2.17-swoole5.1
2024-04-2114:13:53,255 INFO Set uid to user 0 succeeded
2024-04-2114:13:53,266 INFO supervisord started with pid 1
2024-04-2114:13:54,272 INFO spawned: 'webman'with pid 7
Workerman[/app/start.php] start in DEBUG mode
-------------------------------------------------- WORKERMAN --------------------------------------------------
Workerman version:5.0.0 PHP version:8.2.17 Event-loop:Workerman\Events\Swoole
--------------------------------------------------- WORKERS ---------------------------------------------------
proto user worker listen processes state
tcp root webman http://0.0.0.0:8787 8 [OK]
tcp root monitor none 1 [OK]
tcp root push_chart none 1 [OK]
tcp root plugin.webman.push.server websocket://0.0.0.0:8788 1 [OK]
---------------------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
swoole实现协程
协程伪代码
<?php
/**
* @desc Swoole 协程入门
* @author Tinywan(ShaoBo Wan)
* @date 2024/4/22 19:27
*/
declare(strict_types=1);
functiontask1(){
for ($i=0;$i<=5;$i++){
//写入文件,大概要3000微秒
usleep(3000);
echo'[x] [写入文件] ['.$i.'] ' . date('Y-m-d H:i:s') . PHP_EOL;
\Co::sleep(0.001);//挂起当前协程,0.001秒后恢复//相当于切换协程
}
}
functiontask2(){
for ($i=0;$i<=10;$i++){
//发送邮件给500名会员,大概3000微秒
usleep(3000);
echo'[x] [发送邮件] ['.$i.'] ' . date('Y-m-d H:i:s') . PHP_EOL;
Co::sleep(0.001);//挂起当前协程,0.001秒后恢复//相当于切换协程
}
}
functiontask3(){
for ($i=0;$i<=15;$i++){
//模拟插入100条数据,大概3000微秒
usleep(3000);
echo'[x] [插入数据] ['.$i.'] ' . date('Y-m-d H:i:s') . PHP_EOL;
Co::sleep(0.001);//挂起当前协程,0.001秒后恢复//相当于切换协程
}
}
$pid1 = go('task1'); //go函数是swoole的开启协程函数,用于开启一个协程
$pid2 = go('task2');
$pid3 = go('task3');
执行结果
[x] [写入文件] [0] 2024-04-2113:31:37
[x] [发送邮件] [0] 2024-04-2113:31:37
[x] [插入数据] [0] 2024-04-2113:31:37
[x] [写入文件] [1] 2024-04-2113:31:37
[x] [发送邮件] [1] 2024-04-2113:31:37
[x] [插入数据] [1] 2024-04-2113:31:37
[x] [写入文件] [2] 2024-04-2113:31:37
[x] [发送邮件] [2] 2024-04-2113:31:37
[x] [插入数据] [2] 2024-04-2113:31:37
[x] [写入文件] [3] 2024-04-2113:31:37
[x] [发送邮件] [3] 2024-04-2113:31:37
[x] [插入数据] [3] 2024-04-2113:31:37
[x] [写入文件] [4] 2024-04-2113:31:37
[x] [发送邮件] [4] 2024-04-2113:31:37
[x] [插入数据] [4] 2024-04-2113:31:37
[x] [写入文件] [5] 2024-04-2113:31:37
[x] [发送邮件] [5] 2024-04-2113:31:37
[x] [插入数据] [5] 2024-04-2113:31:37
[x] [发送邮件] [6] 2024-04-2113:31:37
[x] [插入数据] [6] 2024-04-2113:31:37
[x] [发送邮件] [7] 2024-04-2113:31:37
[x] [插入数据] [7] 2024-04-2113:31:37
[x] [发送邮件] [8] 2024-04-2113:31:37
[x] [插入数据] [8] 2024-04-2113:31:37
[x] [发送邮件] [9] 2024-04-2113:31:37
[x] [插入数据] [9] 2024-04-2113:31:37
[x] [发送邮件] [10] 2024-04-2113:31:37
[x] [插入数据] [10] 2024-04-2113:31:37
[x] [插入数据] [11] 2024-04-2113:31:37
[x] [插入数据] [12] 2024-04-2113:31:37
[x] [插入数据] [13] 2024-04-2113:31:37
[x] [插入数据] [14] 2024-04-2113:31:37
[x] [插入数据] [15] 2024-04-2113:31:37
为什么要用
sleep
挂起协程实现切换呢?因为swoole的协程是自动的,当协程内遇上
I/O
操作(mysql,redis)等时,swoole的协程会自动切换,运行到下一个协程任务中(切换后,I/O继续执行),直到下一个协程任务完成或者被切换(遇上I/O),如此反复,直到所有协程任务完成,则任务完成。
MySQL 一键协程化
<?php
usefunctionSwoole\Coroutine\run;
usefunctionSwoole\Coroutine\go;
run(function(){
go(function(){
$pdo = new \PDO('mysql:host=192.168.3.29;port=3308;dbname=nacos;charset=utf8', 'root', '123456');
$statement = $pdo->prepare('SELECT * FROM `users`');
$statement->execute();
var_dump($statement->fetchAll());
});
go(function(){
$mysqli = new mysqli('192.168.3.29', 'root', '123456', 'webman-admin', 3308);
$mysqli->set_charset('utf8mb4');
var_dump($mysqli);
});
});
执行结果
array(1) {
[0]=>
array(6) {
["username"]=>
string(5) "nacos"
[0]=>
string(5) "nacos"
["password"]=>
string(60) "$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu"
[1]=>
string(60) "$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu"
["enabled"]=>
int(1)
[2]=>
int(1)
}
}
object(mysqli)#6 (18) {
["affected_rows"]=>
int(0)
["client_info"]=>
string(14) "mysqlnd 8.2.17"
["client_version"]=>
int(80217)
["connect_errno"]=>
int(0)
["connect_error"]=>
NULL
["errno"]=>
int(0)
["error"]=>
string(0) ""
["error_list"]=>
array(0) {
}
["field_count"]=>
int(0)
["host_info"]=>
string(23) "192.168.3.29 via TCP/IP"
["info"]=>
NULL
["insert_id"]=>
int(0)
["server_info"]=>
string(6) "5.7.36"
["server_version"]=>
int(50736)
["sqlstate"]=>
string(5) "00000"
["protocol_version"]=>
int(10)
["thread_id"]=>
int(104)
["warning_count"]=>
int(0)
}
致谢: 感谢 Workerman 和 Swoole 开发团队为 PHP 社区带来的创新和卓越贡献,让我们共同期待 PHP 在实时应用领域的更多突破。
参考
https://www.easyswoole.com/NoobCourse/coroutine.html
https://wiki.swoole.com/#/runtime