首頁 > 後端開發 > PHP8 > 主體

PHP8.1新特性大講解之Fibers with a grain of salt

藏色散人
發布: 2023-02-17 12:16:02
原創
4987 人瀏覽過

本文系翻譯,原文網址:https://stitcher.io/blog/fibers-with-a-grain-of-salt

Fibers with a grain of salt

所以我打算寫一篇關於在PHP 8.1 中使用Fibers纖維的深入部落格文章。我們將從一個基本範例開始,從頭開始解釋它們。這個想法是發送非同步 HTTP 請求並使用纖程並行處理它們。

但是和他們一起玩,我了解到RFC並不是在開玩笑,當它說「不應該直接在應用程式碼中使用Fiber API。Fibers 提供了一個基本的、低階的流控制API來創建更高然後在應用程式程式碼中使用的級抽象」。

因此,與其走這條路並使事情變得過於複雜,我們將討論什麼是纖程概念,為什麼它們在應用程式程式碼中幾乎不可用,以及您到底如何使用非同步 PHP。

首先,一點點理論。

假設您要傳送三個 HTTP 請求並處理它們的組合結果。這樣做的同步方式是發送第一個,等待回應,然後發送第二個,等待,等等。

讓我們用盡可能簡單的圖表來表示這樣的程式流程。你需要從上到下閱讀這張圖表,時間越往下越走。每種顏色代表一個 HTTP 請求。每個請求的彩色部分代表實際運行的PHP 代碼,您伺服器上的CPU 正在執行工作,透明塊代表等待時間:請求需要通過網絡發送,其他伺服器需要處理並發送回. 只有當響應到達時,我們才能再次工作。

PHP8.1新特性大講解之Fibers with a grain of salt

這是一個同步執行流程:傳送、等待、處理、重複。

在並行處理的世界中,我們發送請求但不等待。然後我們發送下一個請求,然後是另一個。只有然後我們等待所有請求。在等待的同時,我們會定期檢查我們的一個請求是否已完成。如果是這種情況,我們可以立即處理。

PHP8.1新特性大講解之Fibers with a grain of salt

您可以看到這種方法如何減少執行時間,因為我們更優化地使用了等待時間。

Fibers 是 PHP 8.1 中的新機制,可讓您更有效地管理這些並行執行路徑。使用生成器和 已經可以實現yield,但是纖維是一個顯著的改進,因為它們是專門為此用例設計的。

您將為每個請求建立一個纖程,並在請求發送後暫停纖程。創建所有三個光纖後,您將遍歷它們,並一一恢復它們。透過這樣做,纖程檢查請求是否已經完成,如果沒有則再次暫停,否則它可以處理回應並最終完成。

你看,纖程是一種啟動、暫停和復原程式隔離部分執行流程的機制。 Fiber 也被稱為「綠色執行緒」:實際上存在於同一進程中的執行緒。這些線程不是由作業系統管理的,而是由運行時管理的——在我們的例子中是 PHP 運行時。它們是管理某些形式的平行程式設計的一種經濟高效的方式。

但請注意,它們並沒有添加任何真正的非同步內容:所有纖程都位於同一個 PHP 進程中,並且一次只能執行一個纖程。這是循環它們並在等待時檢查它們的主進程,該循環通常稱為“事件循環”。

並行性的困難不在於你如何在纖程或生成器上循環,或你想使用的任何機制;它是關於能夠開始一個操作,將它交給一個外部服務,並且只在你想要的時候以非阻塞的方式檢查結果。

看,在前面的例子中,我們假設我們可以只發送一個請求,然後在我們想要的時候檢查它的回應,但這實際上並不像聽起來那麼容易。

沒錯:大多數處理 I/O 的 PHP 函數都沒有內建這種非阻塞功能。事實上,只有少數函數可以做到,而且使用它們非常麻煩。

有一個套接字的例子,它可以被設定為非阻塞,像這樣:

[$read, $write] = stream_socket_pair(
    STREAM_PF_UNIX,
    STREAM_SOCK_STREAM,
    STREAM_IPPROTO_IP
);
 
stream_set_blocking($read, false);
stream_set_blocking($write, false);
登入後複製

透過使用stream_socket_pair(),創建了兩個可用於雙向通訊的套接字。如您所看到的,它們可以使用stream_set_blocking().

假設我們想要實作我們的範例,發送三個請求。我們可以使用套接字來做到這一點,但我們需要在它之上自己實作 HTTP 協定。這正是nox7所做的,該用戶在Reddit上分享了一個小型概念證明,以展示如何使用光纖和套接字發送 HTTP GET 請求。你真的想在你的應用程式程式碼中這樣做嗎?

至少對我來說,答案是「否」。這正是 RFC 警告的內容;我不生氣。相反,我們鼓勵使用現有的非同步框架之一:Amp或ReactPHP。

例如,使用 ReactPHP,我們可以這樣寫:

$loop = React\EventLoop\Factory::create();
$browser = new Clue\React\Buzz\Browser($loop);
$promises = [
    $browser->get('https://example.com/1'),
    $browser->get('https://example.com/2'),
    $browser->get('https://example.com/3'),
];
$responses = Block\awaitAll($promises, $loop);
登入後複製

与手动创建套接字连接相比,这是一个更好的示例。这就是 RFC 的意思:应用程序开发人员不需要担心纤程,它是 Amp 或 ReactPHP 等框架的实现细节。

不过,这给我们带来了一个问题:与我们已经可以用发电机做的事情相比,纤维有什么好处?RFC 是这样解释的:

与无堆栈生成器不同,每个 Fiber 都有自己的调用堆栈,允许它们在深度嵌套的函数调用中暂停。声明中断点的函数(即调用 Fiber::suspend())不需要更改其返回类型,这与使用 yield 的函数必须返回 Generator 实例不同。

Fiber 可以在任何函数调用中挂起,包括那些从 PHP VM 内部调用的函数,例如提供给 array_map 的函数或迭代器对象上的 foreach 调用的方法。

很明显,纤程在语法和灵活性方面都有显着的改进。但与 Go 及其“ goroutines ”相比,它们还不算什么。

要使异步 PHP 在没有框架开销的情况下成为主流,仍然缺少许多功能,而 Fiber 是朝着正确方向迈出的良好一步,但我们还没有做到这一点。

所以就是这样。如果您不是 Amp、ReactPHP 或较小的异步 PHP 框架的维护者,那么实际上没有什么可说的。也许更多的框架或库将开始合并它们?

同时,还有Swoole——一个 PHP 扩展,它实际上将几个核心功能修改为非阻塞。Swoole 本身是一个中文项目,在涉及英语时通常没有很好的文档记录,但最近 Laravel宣布与它进行第一方集成。也许这是将 PHP 推向更异步模型的更好策略:可选择将 Swoole 或其他扩展与 Laravel 和 Symfony 等框架集成?

以上是PHP8.1新特性大講解之Fibers with a grain of salt的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板