溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP與Go的合體有什么優(yōu)勢

發(fā)布時間:2021-11-12 14:44:19 來源:億速云 閱讀:205 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“PHP與Go的合體有什么優(yōu)勢”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

常規(guī) PHP 開發(fā)環(huán)境

在講述 Go 如何改善 PHP 死亡模型前,先了解一下常規(guī) PHP 開發(fā)環(huán)境。

通常,應用運行于 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)點。你不需要太擔心內(nèi)存消耗,所有進程都是完全隔離的,如果其中一個進程「死亡」,它將自動重新創(chuàng)建,并且不會影響其他進程。但是,當你嘗試擴展應用程序時,這種方式會有缺點產(chǎn)生。

典型 PHP 環(huán)境的缺點和低效性

如果你從事 PHP 的專業(yè)開發(fā),那么你就知道從哪兒開始創(chuàng)建一個新項目——選擇框架。它是一個用于依賴注入、ORM、轉(zhuǎn)化和模板方法的庫。當然,所有用戶輸入的數(shù)據(jù)都可以方便地放在一個對象中(Symfony / HttpFoundation 或者 PSR-7)。這些框架很棒!

但一切都有它的代價。在任何企業(yè)框架中,為了處理一個簡單的用戶請求或訪問數(shù)據(jù)庫,您必須加載至少幾十個文件,創(chuàng)建許多類,并解析多個配置。但最糟糕的是,在每個任務完成后,您需要重置所有內(nèi)容并重新啟動:您剛剛啟動的所有代碼都將變得無用,在它的幫助下,您將無法處理另一個請求。把這件事告訴任何用其他語言編寫的程序員——你會看到他臉上的困惑。

多年來,PHP工程師一直在尋找解決此問題的方法,他們使用了延遲加載技術、微幀、優(yōu)化庫、緩存等。但最終,您仍然必須放棄整個應用程序,重新開始*(譯者注:隨著PHP7.4中預加載的出現(xiàn),這個問題將得到部分解決)

一個PHP進程能處理多個請求嗎?

您可以編寫持續(xù)時間超過幾分鐘的PHP腳本(最多幾小時或幾天):例如Cron任務、CSV解析器、隊列處理程序。所有這些工作遵循一個模式:他們獲取一條任務,處理完它,然后獲取下一個任務。代碼常駐在內(nèi)存中,因此避免了額外的操作來加載框架和應用程序,節(jié)約了寶貴時間。

但是開發(fā)長時間運行的腳本并不是那么容易。任何錯誤都會殺死進程,內(nèi)存溢出會導致崩潰,而且不能用F5來調(diào)試程序了。

自PHP 7后情況有所改善:可靠的垃圾收集器出現(xiàn)了,它變得更容易處理錯誤,內(nèi)核的擴展可以避免內(nèi)存泄漏。是的,工程師仍然需要仔細處理內(nèi)存并記住代碼中的狀態(tài)的問題(有哪一種語言能讓你可以不關注這些事情呢?)當然,在PHP 7中,驚喜并不多。

是否可以采用一種 常駐 PHP 腳本的模型,將其用于處理 HTTP 請求等更瑣碎的任務,從而消除對每個請求都從頭開始下載所有內(nèi)容的需要?

要解決這個問題,首先需要實現(xiàn)一個服務器應用程序,該應用程序可以接收 HTTP 請求并將它們逐個重定向到 PHP worker,而不是每次都殺死它。

我們知道我們可以用純 PHP(PHP-PM)或 C 擴展(Swoole)編寫 web 服務器。盡管每種方法都有其優(yōu)點,但這兩種選擇都不適合我們 —— 我想要更多的東西。我們需要的不僅僅是一個 web 服務器 —— 我們希望得到一個解決方案,可以使我們避免與 PHP 中的「重啟動」相關的問題,同時可以輕松地為特定的應用程序進行調(diào)整和擴展。也就是說,我們需要一個應用服務器。

Go 可以幫助解決這個問題嗎?我們知道它可以,因為這種語言將應用程序編譯成單個的二進制文件; 它是跨平臺的; 使用自己的并行處理模型(并發(fā))和用于處理 HTTP 的庫; 最后,我們可以把更多的開源庫集成到我們的程序中。

合并兩種編程語言遇到的困難

首先,有必要確定兩個或多個應用程序之間如何相互通信。

例如,使用 Alex Palaestras 的 go-php 庫, 可以實現(xiàn) PHP 和 Go 進程 (如 Apache 中的 mod_php) 之間的內(nèi)存共享。但是這個庫的功能限制了我們使用它解決問題。

我們決定使用另一種更常見的方法:通過使用 sockets / pipelines 來構建進程之間的交互。 這種方法在過去十年中已經(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 服務 的功能。 這個功能在后面的開發(fā)中對我們有很大的幫助,因為我們可以輕松地將 Go 庫集成到 PHP 應用程序中。這項工作的結(jié)果可以在我們的另一個開源產(chǎn)品 Goridge 中看到。

在多個 PHP Worker 之間分配任務

在交互機制實現(xiàn)之后,我們開始思考如何更好地將任務轉(zhuǎn)移到 PHP 進程中。當任務到達時,應用服務器必須選擇一個空閑的 worker 來執(zhí)行它。 如果 worker 進程因錯誤而終止或「死亡」,我們將清除它并創(chuàng)建一個新的。 如果 worker 進程成功執(zhí)行,我們會將它返回到可用于執(zhí)行任務的 worker 池中。

PHP與Go的合體有什么優(yōu)勢

為了存儲活躍的 worker 進程池,我們使用了一個 緩沖通道 , 為了從池中清除意外「死亡」的工作進程,我們添加了一種跟蹤錯誤和 worker 進程狀態(tài)的機制。

最終,我們得到了一個可以運行的 PHP 服務器,它能夠處理任何以二進制形式呈現(xiàn)的請求。

為了讓我們的應用程序作為 web 服務器開始工作,我們必須選擇一個可靠的 PHP 標準來處理任何傳入的 HTTP 請求。在我們的例子中,我們只需將簡單的 net / http 請求從 Go  轉(zhuǎn)換 為 PSR-7 格式,這樣它就可以與目前大多數(shù)可用的 PHP 框架兼容。

由于 PSR-7 被認為是不可變的(有人會說在技術上不是),開發(fā)人員必須編寫那些在原則上不將請求視為全局實體的應用程序。這完全符合 PHP 常駐進程的概念。我們的最終實現(xiàn)(尚未收到名稱)如下所示:

PHP與Go的合體有什么優(yōu)勢

RoadRunner - 高 - 性能 PHP 應用服務器

我們的第一個測試任務是一個 API 后端,在該后端上,會周期性地出現(xiàn)不可預測的突發(fā)請求(比平時更頻繁)。雖然在大多數(shù)情況下 nginx capabilities 是足夠的,但是我們經(jīng)常因為無法在預期的負載增加下快速平衡系統(tǒng)而遇到 502 錯誤。

為解決此問題,我們在 2018 年初部署了第一臺 PHP / Go 應用服務器。并立即取得了驚人的效果!我們不僅完全消除了 502 錯誤,并且還將服務器的數(shù)量減少了三分之二,節(jié)省了大量資金并解決了令工程師和產(chǎn)品經(jīng)理頭痛的問題。

在年中的時候,我們改進了我們的方案,在 MIT 許可下將其發(fā)布在 GitHub 上,并命名為 RoadRunner, 從而強調(diào)了它驚人的速度和效率。

RoadRunner 是如何改進你的開發(fā)堆棧的

RoadRunner 的使用允許我們在 Go 端使用中間件 net/http ,甚至在請求進入 PHP 之前進行 JWT 驗證,以及在 Prometheus 中處理 WebSocket 和全局聚合狀態(tài)。

由于內(nèi)置的 RPC,你可以在不編寫擴展包的情況下,在 PHP 中打開任何 Go 庫的 API。更重要的是,使用 RoadRunner,你可以部署不同于 HTTP 的新服務器。示例包括在 PHP 中運行 AWS Lambda 處理器 , 創(chuàng)建強大的隊列 選擇器, 甚至將  gRPC 添加到我們的應用程序中。

同時使用 PHP 和 Go ,對解決方案有了穩(wěn)定的提升,在一些測試中將應用程序性能提高了 40 倍,改進了調(diào)試工具,實現(xiàn)了與 Symfony 框架的集成,并添加了對 HTTPS、HTTP/2、插件和 PSR-17 的支持。

“PHP與Go的合體有什么優(yōu)勢”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI