概述
Workerman 5.0 版本中的異步HTTP協程用戶端元件是一個基于PHP協程的高性能HTTP用戶端,它能夠充分利用PHP的異步特性來提高HTTP請求的效率和性能。這個元件允許開發者在編寫PHP代碼時,以同步的方式發送異步HTTP請求,進而使得編寫的代碼更加簡潔易懂,同時也能夠處理大量的并發請求。
這個元件的特點包括:
- 異步非阻塞:所有的請求和響應都是異步進行的,不會阻塞主線程,這意味着可以同時處理多個HTTP請求和響應。
- 内置連接配接池:為了提高效率和性能,該元件内置了連接配接池,可以複用TCP連接配接,減少建立和關閉連接配接的開銷。
- 符合PSR-7規範:消息請求和響應都符合PSR-7規範,這使得它能夠與遵循該規範的其他PHP元件和庫無縫內建。
- 支援多種協定:除了HTTP和HTTPS協定,該元件還支援WebSocket、WSS等協定,使其能夠應對更多的應用場景。
安裝
注意:5.0需要PHP版本大于8.2.4及以上版本
通過php -v檢視你目前PHP版本資訊
php -v
PHP 8.2.18 (cli) (built: Apr 11 2024 19:20:54) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.18, Copyright (c) Zend Technologies
with Zend OPcache v8.2.18, Copyright (c), by Zend Technologies
workerman 5.0 安裝
composer require workerman/workerman v5.0.0-beta.7
revolt/event-loop 安裝
Revolt是什麼?
Revolt是并發PHP應用程式的堅如磐石的事件循環。通常的PHP應用程式将大部分時間花在等待I/O上。雖然PHP是單線程的,但可以使用協作多任務來允許并發性,方法是使用等待時間來做不同的事情。
PHP的傳統同步執行流程很容易了解。一次隻做一件事。如果查詢資料庫,則發送查詢并等待資料庫伺服器的響應。一旦你有了答案,你就可以開始做下一件事。
ReactPHP和其他庫已經在PHP中提供了很長一段時間的協作多任務。然而,它們的事件驅動特性與許多現有的接口不相容,需要不同的思維模型。PHP 8.1内置了fibers,它提供了協作多線程。調用可以是異步的,沒有promise或回調,同時仍然允許非阻塞I/O。
每個使用協同多任務的應用程式都需要一個排程器(也稱為事件循環),這個包提供了這個排程器。Revolt是結合了React和ReactPHP的事件循環實作的多年經驗的結果。然而,它并不是一個用于編寫并發PHP應用程式的成熟架構,而隻是提供了必要的公共基礎。不同的(強烈的)固執己見的庫可以在它的基礎上建構,React和ReactPHP将繼續共存。
Revolt 支援事件
- Defer 回調在事件循環的下一次疊代中執行。如果有延遲排程,事件循環不會在疊代之間等待。
- Delay 在指定的秒數後執行回調。秒的分數可以表示為浮點數。
- Repeat 在指定的秒數後重複執行回調。秒的分數可以表示為浮點數。
- Stream readable 當流上有資料要讀取或連接配接關閉時,将執行回調。
- Stream writable 當寫緩沖區中有足夠的空間來接受要寫入的新資料時,就會執行回調。
- Signal 當程序從作業系統接收到特定信号時執行回調。
安裝
composer require revolt/event-loop
workerman/http-client安裝
workerman/http-client是一個異步http用戶端元件。所有請求響應異步非阻塞,内置連接配接池,消息請求和響應符合PSR7規範。更多了解:https://www.workerman.net/doc/workerman/components/workerman-http-client.html
composer require workerman/http-client
編寫代碼
http.php僞代碼
<?php
/**
* @desc 僞代碼
* @author Tinywan(ShaoBo Wan)
* @date 2024/11/14 15:14
*/
declare(strict_types=1);
use Workerman\Worker;
require_once '../vendor/autoload.php';
try {
$worker = new Worker();
$worker->onWorkerStart = function () {
$http = new Workerman\Http\Client();
$response = $http->get('https://www.tinywan.com/');
var_dump($response->getStatusCode());
echo $response->getBody() . PHP_EOL;
$response = $http->post('https://www.tinywan.com/', ['key1' => 'value1', 'key2' => 'value2']);
var_dump($response->getStatusCode());
echo $response->getBody() . PHP_EOL;
$response = $http->request('https://www.tinywan.com/', [
'method' => 'GET',
'version' => '1.1',
'headers' => ['Connection' => 'keep-alive'],
'data' => ['key1' => 'value1', 'key2' => 'value2'],
]);
echo $response->getBody() . PHP_EOL;
};
Worker::runAll();
} catch (Throwable $throwable) {
var_dump($throwable->getMessage());
}
啟動服務
/var/www/workerman5.x-demo/coroutine # php http.php start
Workerman[http.php] start in USER mode
---------------------------------------- WORKERMAN -----------------------------------------
Workerman version:5.0.0-beta.7 PHP version:8.2.18 Event-loop:Workerman\Events\Revolt
----------------------------------------- WORKERS ------------------------------------------
proto user worker listen processes state
tcp root none none 1 [OK]
--------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
注意:這裡使用Event-loop:Workerman\Events\Revolt事件
執行結果
int(200)
int(405)
int(200)
http-client 協程異步并發
<?php
/**
* @desc 僞代碼
* @author Tinywan(ShaoBo Wan)
* @date 2024/11/14 15:14
*/
declare(strict_types=1);
use Workerman\Worker;
use \Workerman\Connection\TcpConnection;
use \Workerman\Protocols\Http\Request;
require_once '../vendor/autoload.php';
// 建立一個Worker監聽8217端口,使用http協定通訊
$httpWorker = new Worker("http://0.0.0.0:8217");
// 啟動8個程序對外提供服務
$httpWorker->count = 8;
// 接收到浏覽器發送的資料時回複給浏覽器
$httpWorker->onMessage = function (TcpConnection $connection, Request $request) {
$http = new \Workerman\Http\Client();
$count = 50;
$result = [];
while ($count--) {
$startTime = microtime(true);
echo '開始時間:' . $startTime . PHP_EOL;
$response = $http->get('https://api.tinywan.com/systems/website');
$endTime = microtime(true);
echo '結束時間:' . $endTime . PHP_EOL;
$result[] = sprintf('第%d個 | 耗時%s秒 | 狀态碼%d', $count, $endTime - $startTime, $response->getStatusCode());
}
$connection->send(json_encode($result));
};
// 運作worker
Worker::runAll();
執行結果(未完,待續……)
[
"第49個 | 耗時0.53055596351624秒 | 狀态碼200",
"第48個 | 耗時0.11245107650757秒 | 狀态碼200",
"第47個 | 耗時0.13903284072876秒 | 狀态碼200",
"第46個 | 耗時0.21533107757568秒 | 狀态碼200",
"第45個 | 耗時0.11252999305725秒 | 狀态碼200",
"第44個 | 耗時0.15401482582092秒 | 狀态碼200",
"第43個 | 耗時0.10678505897522秒 | 狀态碼200",
"第42個 | 耗時0.099571943283081秒 | 狀态碼200",
"第41個 | 耗時0.12561202049255秒 | 狀态碼200",
"第40個 | 耗時0.10563802719116秒 | 狀态碼200",
"第39個 | 耗時0.11354088783264秒 | 狀态碼200",
"第38個 | 耗時0.1011688709259秒 | 狀态碼200",
"第37個 | 耗時0.20793986320496秒 | 狀态碼200",
"第36個 | 耗時0.1089551448822秒 | 狀态碼200",
"第35個 | 耗時0.092885971069336秒 | 狀态碼200",
"第34個 | 耗時0.10161209106445秒 | 狀态碼200",
"第33個 | 耗時0.20717096328735秒 | 狀态碼200",
"第32個 | 耗時0.20546984672546秒 | 狀态碼200",
"第31個 | 耗時0.11044192314148秒 | 狀态碼200",
"第30個 | 耗時0.12123489379883秒 | 狀态碼200",
"第29個 | 耗時0.11858606338501秒 | 狀态碼200",
"第28個 | 耗時0.17020511627197秒 | 狀态碼200",
"第27個 | 耗時0.095601081848145秒 | 狀态碼200",
"第26個 | 耗時0.11254286766052秒 | 狀态碼200",
"第25個 | 耗時0.19883704185486秒 | 狀态碼200",
"第24個 | 耗時0.20402407646179秒 | 狀态碼200",
"第23個 | 耗時0.10713791847229秒 | 狀态碼200",
"第22個 | 耗時0.11914396286011秒 | 狀态碼200",
"第21個 | 耗時0.094994068145752秒 | 狀态碼200",
"第20個 | 耗時0.10224294662476秒 | 狀态碼200",
"第19個 | 耗時0.11380887031555秒 | 狀态碼200",
"第18個 | 耗時0.10260701179504秒 | 狀态碼200",
"第17個 | 耗時0.28102612495422秒 | 狀态碼200",
"第16個 | 耗時0.10411977767944秒 | 狀态碼200",
"第15個 | 耗時0.10007786750793秒 | 狀态碼200",
"第14個 | 耗時0.095911979675293秒 | 狀态碼200",
"第13個 | 耗時0.094711065292358秒 | 狀态碼200",
"第12個 | 耗時0.09196400642395秒 | 狀态碼200",
"第11個 | 耗時0.10585021972656秒 | 狀态碼200",
"第10個 | 耗時0.092756032943726秒 | 狀态碼200",
"第9個 | 耗時0.23688101768494秒 | 狀态碼200",
"第8個 | 耗時0.20317101478577秒 | 狀态碼200",
"第7個 | 耗時0.10062909126282秒 | 狀态碼200",
"第6個 | 耗時0.20747685432434秒 | 狀态碼200",
"第5個 | 耗時0.11253881454468秒 | 狀态碼200",
"第4個 | 耗時0.12536215782166秒 | 狀态碼200",
"第3個 | 耗時0.17252016067505秒 | 狀态碼200",
"第2個 | 耗時0.12250709533691秒 | 狀态碼200",
"第1個 | 耗時0.10875701904297秒 | 狀态碼200",
"第0個 | 耗時0.10053586959839秒 | 狀态碼200"
]
倉庫位址:https://github.com/Tinywan/workerman5.x-demo