php reactor 实例,PHP 的 Web 運行原理 ( 3 ) - PHP Reactor 實現之 reactPHP

上一篇文章 PHP 的 Web 運行原理 ( 2 ) - 非阻塞 I/O 之 Reactor 模式

我們理解到實現非阻塞 I/O 的 reactor 模式以後,接下來本篇文章我們將來要說明,在 php 中的 reactor 實現 reactPHP

本篇文章分為以下三個章節 :

reactPHP 基本概念

reactPHP 非阻塞 I/O 實現

reactPHP 使用時注意事項

reactPHP 基本概念

reactPHP 官網寫這一段話 :

Event-driven, non-blocking I/O with PHP

它是一個用 php 所寫的 libaray,可以幫助我們做以下的事情 :

可以建立一個非阻塞 I/O 的網路服務。

可以建立一個定時排程服務。

http server 的範例

下面就是官網首頁的範例,我們可以用它簡單的建立一個非阻塞 I/O 的 http server,就如同 nodejs 一樣。

$loop = React\EventLoop\Factory::create();

$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) {

return new React\Http\Response(

200,

array('Content-Type' => 'text/plain'),

"Hello World!\n"

);

});

$socket = new React\Socket\Server(8080, $loop);

$server->listen($socket);

echo "Server running at http://127.0.0.1:8080\n";

$loop->run();

排程服務的範例

$loop = React\EventLoop\Factory::create();

// 5 秒後執行

$loop->addPeriodicTimer(5, function () {

echo "Hi Mark";

});

$loop->run();

reactPHP 非阻塞 I/O 實現

那 reactPHP 它是如何實現非阻塞 I/O 模式呢 ?

它就是如我們標題所說,它使用 reactor 模式

來實現非阻塞 I/O 模式,並且它與 nodejs 一樣使用 single process 的 reactor 模式。

備註: 為什麼 single process 可以做到非阻塞 I/O 請參考前一篇文章。

架構圖如下,就是一個 reactor 機制,其中它的 process 裡面就有所謂的 I/O 多路復用技術。

假設我們有一段程式碼要執行,那麼它的運行原理流程如下 :

建立 event loop。

將 addPeriodicTimer 5 秒後要執行的事件丟到 queue 中。

執行 event loop。(也就是開始跑無窮迴圈)

event loop 在 5 秒時,發現有個要執行的任務 callback function

執行 echo "Hi Mark"。

將立 http 請求,並將它丟到 queue 中。

event loop 當發現 I/O 操作有回復時,則執行 callback function

echo $chunk。

(1) $loop = React\EventLoop\Factory::create();

$client = new React\HttpClient\Client($loop);

// 5 秒後執行

(2) $loop->addPeriodicTimer(5, function () {

(4)

(5) echo "Hi Mark";

(6) $request = $client->request('GET', 'https://github.com/');

$request->on('response', function ($response) {

$response->on('data', function ($chunk) {

(7) echo $chunk;

});

$response->on('end', function() {

echo 'DONE';

});

});

(3) $loop->run();

使用時注意事項

reactPHP 理論上是 php 版的 nodejs 但實際使用要注意,不是。

假設我們使用 reactPHP 然後來寫一個 http server。

然後當 server 收到一個請求時,它會再使用 file_get_contents

這個方法去打某個 api,這 api 需要一分鐘左右才能回應。

require __DIR__ . '/vendor/autoload.php';

$loop = React\EventLoop\Factory::create();

$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) use ($client) {

// ----------------------------------------------------

var_dump('wait...');

// 假設這一段要執行一分鐘。

$response = file_get_contents('http://127.0.0.1:3000');

var_dump('done !...');

// ----------------------------------------------------

return new React\Http\Response(

200,

array('Content-Type' => 'text/plain'),

"Hello World!\n"

);

});

$socket = new React\Socket\Server(8080, $loop);

$server->listen($socket);

echo "Server running at http://127.0.0.1:8080\n";

$loop->run();

假設往這個使用 reactPHP 寫的 http server,發送兩次請求,上面的 wait 會看到幾次呢 ?

答案是 : 1 次

因為第一次請求時,就將整個 process 給阻塞住了,所以第二個請求完全無法處理。

它不是說它有提供非阻塞 I/O 的功能嗎 ?

嗯對的,它有提供,但是前提假設為,你要使用它。

你在寫 nodejs 時,上面這個相似範例 process 就不會被阻塞住,因為它在給 v8 處理完 binding c++ 階段時,會將所有的 I/O 操作執行完並且丟到 event loop 機制中,所以在 nodejs 操作 I/O 時,你什麼都沒做,就會是非阻塞的 I/O 操作。

而在 reactPHP 中,你要自已處理又或是使用它所提供的 http client 才能讓變成非阻塞 I/O 的操作。如下範例。

require __DIR__ . '/vendor/autoload.php';

$loop = React\EventLoop\Factory::create();

$client = new React\HttpClient\Client($loop);

$server = new React\Http\Server(function (Psr\Http\Message\ServerRequestInterface $request) use ($client) {

// ----------------------------------------------------

var_dump('wait...');

$request = $client->request('GET', 'http://127.0.0.1:3000');

$request->on('response', function ($response) {

$response->on('data', function ($chunk) {

echo $chunk;

});

$response->on('end', function() {

echo 'DONE';

});

var_dump('done !...');

// ----------------------------------------------------

return new React\Http\Response(

200,

array('Content-Type' => 'text/plain'),

"Hello World!\n"

);

});

$socket = new React\Socket\Server(8080, $loop);

$server->listen($socket);

echo "Server running at http://127.0.0.1:8080\n";

$loop->run();

結論

本篇文章中我們學習了幾個重點:

reactPHP 基本概念

就是這段話。

Event-driven, non-blocking I/O with PHP

reactPHP 非阻塞 I/O 實現

它使用 single process 的 reactor 模式

來實現。

使用時注意事項

在使用它時注意,你要確保你所有的 I/O 操作,都有丟到 event loop 中,否則,它仍然是阻塞 I/O 操作,就如同範例一樣。

參考資料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值