概述
在現代的互聯網套用開發中,效能和即時性是衡量一個套用成功的關鍵指標。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