您好,登錄后才能下訂單哦!
這篇文章主要介紹“RoadRunner有哪些特性”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“RoadRunner有哪些特性”文章能幫助大家解決問題。
在講述 Go 如何改善 PHP 死亡模型前,先了解一下常規(guī) PHP 開發(fā)環(huán)境。
通常,應(yīng)用運行于 nginx 和 PHP-FPM 上。nginx 處理靜態(tài)請求,而動態(tài)請求則被重定向給 PHP-FPM,并由其執(zhí)行 PHP 代碼。也許你用的是 Apache 和 mod_php,但是他們原理相同,運行起來只有細微的差別。
看看 PHP-FPM 是如何執(zhí)行代碼的。當收到請求,PHP-FPM 初始化 PHP 子進程,并將請求的詳細信息轉(zhuǎn)發(fā)給它,作為其狀態(tài)的一部分(_GET, _POST, _SERVER 等)。
在 PHP 腳本執(zhí)行期間,狀態(tài)將無法更改,因此只能通過一種方式獲取一組新的輸入數(shù)據(jù):清除進程內(nèi)存并再次初始化它。
這種性能模型有許多優(yōu)點。你不需要太擔(dān)心內(nèi)存消耗,所有進程都是完全隔離的,如果其中一個進程「死亡」,它將自動重新創(chuàng)建,并且不會影響其他進程。但是,當你嘗試擴展應(yīng)用程序時,這種方式會有缺點產(chǎn)生。
如果你從事 PHP 的專業(yè)開發(fā),那么你就知道從哪兒開始創(chuàng)建一個新項目 —— 選擇框架。它是一個用于依賴注入、ORM、轉(zhuǎn)化和模板方法的庫。當然,所有用戶輸入的數(shù)據(jù)都可以方便地放在一個對象中(Symfony / HttpFoundation 或者 PSR-7)。這些框架很棒!
但一切都有它的代價。在任何企業(yè)框架中,為了處理一個簡單的用戶請求或訪問數(shù)據(jù)庫,您必須加載至少幾十個文件,創(chuàng)建許多類,并解析多個配置。但最糟糕的是,在每個任務(wù)完成后,您需要重置所有內(nèi)容并重新啟動:您剛剛啟動的所有代碼都將變得無用,在它的幫助下,您將無法處理另一個請求。把這件事告訴任何用其他語言編寫的程序員 —— 你會看到他臉上的困惑。
多年來,PHP 工程師一直在尋找解決此問題的方法,他們使用了延遲加載技術(shù)、微幀、優(yōu)化庫、緩存等。但最終,您仍然必須放棄整個應(yīng)用程序,重新開始 *(譯者注:隨著 PHP7.4 中預(yù)加載的出現(xiàn),這個問題將得到部分解決)
您可以編寫持續(xù)時間超過幾分鐘的 PHP 腳本(最多幾小時或幾天):例如 Cron 任務(wù)、CSV 解析器、隊列處理程序。所有這些工作遵循一個模式:他們獲取一條任務(wù),處理完它,然后獲取下一個任務(wù)。代碼常駐在內(nèi)存中,因此避免了額外的操作來加載框架和應(yīng)用程序,節(jié)約了寶貴時間。
但是開發(fā)長時間運行的腳本并不是那么容易。任何錯誤都會殺死進程,內(nèi)存溢出會導(dǎo)致崩潰,而且不能用 F5 來調(diào)試程序了。
自 PHP 7 后情況有所改善:可靠的垃圾收集器出現(xiàn)了,它變得更容易處理錯誤,內(nèi)核的擴展可以避免內(nèi)存泄漏。是的,工程師仍然需要仔細處理內(nèi)存并記住代碼中的狀態(tài)的問題(有哪一種語言能讓你可以不關(guān)注這些事情呢?)當然,在 PHP 7 中,驚喜并不多。
是否可以采用一種 常駐 PHP 腳本的模型,將其用于處理 HTTP 請求等更瑣碎的任務(wù),從而消除對每個請求都從頭開始下載所有內(nèi)容的需要?
要解決這個問題,首先需要實現(xiàn)一個服務(wù)器應(yīng)用程序,該應(yīng)用程序可以接收 HTTP 請求并將它們逐個重定向到 PHP worker,而不是每次都殺死它。
我們知道我們可以用純 PHP(PHP-PM)或 C 擴展(Swoole)編寫 web 服務(wù)器。盡管每種方法都有其優(yōu)點,但這兩種選擇都不適合我們 —— 我想要更多的東西。我們需要的不僅僅是一個 web 服務(wù)器 —— 我們希望得到一個解決方案,可以使我們避免與 PHP 中的「重啟動」相關(guān)的問題,同時可以輕松地為特定的應(yīng)用程序進行調(diào)整和擴展。也就是說,我們需要一個應(yīng)用服務(wù)器。
Go 可以幫助解決這個問題嗎?我們知道它可以,因為這種語言將應(yīng)用程序編譯成單個的二進制文件; 它是跨平臺的; 使用自己的并行處理模型(并發(fā))和用于處理 HTTP 的庫; 最后,我們可以把更多的開源庫集成到我們的程序中。
首先,有必要確定兩個或多個應(yīng)用程序之間如何相互通信。
例如,使用 Alex Palaestras 的 go-php 庫,可以實現(xiàn) PHP 和 Go 進程 (如 Apache 中的 mod_php) 之間的內(nèi)存共享。但是這個庫的功能限制了我們使用它解決問題。
我們決定使用另一種更常見的方法:通過使用 sockets /pipelines 來構(gòu)建進程之間的交互。 這種方法在過去十年中已經(jīng)證明了其可靠性,并且在操作系統(tǒng)級別得到了很好的優(yōu)化。
首先,我們創(chuàng)建了一個簡單的二進制協(xié)議,用于在進程之間交換數(shù)據(jù)和處理傳輸錯誤。在其最簡單的形式中, 這種類型的協(xié)議類似于 一個具有固定大小的 packet 頭 (在我們的示例中為 17 個字節(jié)) 的 netstring ,其中包含的信息有 packet 的類型,其大小和二進制掩碼的信息,用來檢查數(shù)據(jù)的完整性。
在 PHP 端,我們使用了 pack 函數(shù) ,在 Go 端,使用了 編碼 / 二進制 庫。
有一個協(xié)議對我們來說有點過時,我們添加了直接 從 PHP 調(diào)用 net /rpc Go 服務(wù) 的功能。 這個功能在后面的開發(fā)中對我們有很大的幫助,因為我們可以輕松地將 Go 庫集成到 PHP 應(yīng)用程序中。這項工作的結(jié)果可以在我們的另一個開源產(chǎn)品 Goridge 中看到。
在交互機制實現(xiàn)之后,我們開始思考如何更好地將任務(wù)轉(zhuǎn)移到 PHP 進程中。當任務(wù)到達時,應(yīng)用服務(wù)器必須選擇一個空閑的 worker 來執(zhí)行它。 如果 worker 進程因錯誤而終止或「死亡」,我們將清除它并創(chuàng)建一個新的。 如果 worker 進程成功執(zhí)行,我們會將它返回到可用于執(zhí)行任務(wù)的 worker 池中。
為了存儲活躍的 worker 進程池,我們使用了一個 緩沖通道 , 為了從池中清除意外「死亡」的工作進程,我們添加了一種跟蹤錯誤和 worker 進程狀態(tài)的機制。
最終,我們得到了一個可以運行的 PHP 服務(wù)器,它能夠處理任何以二進制形式呈現(xiàn)的請求。
為了讓我們的應(yīng)用程序作為 web 服務(wù)器開始工作,我們必須選擇一個可靠的 PHP 標準來處理任何傳入的 HTTP 請求。在我們的例子中,我們只需將簡單的 net /http 請求從 Go 轉(zhuǎn)換 為 PSR-7 格式,這樣它就可以與目前大多數(shù)可用的 PHP 框架兼容。
由于 PSR-7 被認為是不可變的(有人會說在技術(shù)上不是),開發(fā)人員必須編寫那些在原則上不將請求視為全局實體的應(yīng)用程序。這完全符合 PHP 常駐進程的概念。我們的最終實現(xiàn)(尚未收到名稱)如下所示:
我們的第一個測試任務(wù)是一個 API 后端,在該后端上,會周期性地出現(xiàn)不可預(yù)測的突發(fā)請求(比平時更頻繁)。雖然在大多數(shù)情況下 nginx capabilities 是足夠的,但是我們經(jīng)常因為無法在預(yù)期的負載增加下快速平衡系統(tǒng)而遇到 502 錯誤。
為解決此問題,我們在 2018 年初部署了第一臺 PHP / Go 應(yīng)用服務(wù)器。并立即取得了驚人的效果!我們不僅完全消除了 502 錯誤,并且還將服務(wù)器的數(shù)量減少了三分之二,節(jié)省了大量資金并解決了令工程師和產(chǎn)品經(jīng)理頭痛的問題。
在年中的時候,我們改進了我們的方案,在 MIT 許可下將其發(fā)布在 GitHub 上,并命名為 RoadRunner, 從而強調(diào)了它驚人的速度和效率。
RoadRunner 的使用允許我們在 Go 端使用中間件 net/http ,甚至在請求進入 PHP 之前進行 JWT 驗證,以及在 Prometheus 中處理 WebSocket 和全局聚合狀態(tài)。
由于內(nèi)置的 RPC,你可以在不編寫擴展包的情況下,在 PHP 中打開任何 Go 庫的 API。更重要的是,使用 RoadRunner,你可以部署不同于 HTTP 的新服務(wù)器。示例包括在 PHP 中運行 AWS Lambda 處理器,創(chuàng)建強大的隊列 選擇器, 甚至將 gRPC 添加到我們的應(yīng)用程序中。
同時使用 PHP 和 Go ,對解決方案有了穩(wěn)定的提升,在一些測試中將應(yīng)用程序性能提高了 40 倍,改進了調(diào)試工具,實現(xiàn)了與 Symfony 框架的集成,并添加了對 HTTPS、HTTP/2、插件和 PSR-17 的支持。
關(guān)于“RoadRunner有哪些特性”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。