Swoole 驅動的 Laravel 應用優(yōu)化原理

Swoole VS PHP-FPM
我們先來看看傳統(tǒng)的基于 PHP-FPM 的 Laravel 應用啟動和請求處理流程:

PHP生命周期.png

如上圖所示渐裸,PHP-FPM 位于 SAPI 層废恋,PHP 底層在接收到來自 Nginx 轉發(fā)過來的 PHP 請求時汁政,會將其交給某個空閑的 PHP-FPM 進程來處理,PHP-FPM 進程會在啟動階段設置 HTTP 環(huán)境變量,然后通過 PHP 核心代碼初始化所有已經啟用的 PHP 模塊(即擴展),并對此次請求上下文進行初始化觉鼻,完成,這些操作后再調用 Zend 引擎來編譯并執(zhí)行業(yè)務邏輯代碼(進入 Laravel 項目队橙,從入口文件開始執(zhí)行)坠陈,具體的代碼執(zhí)行流程如下:
執(zhí)行流程.jpg

Zend 引擎會檢查 OpCode 緩存,如果代碼片段已經緩存捐康,則從緩存中讀取并執(zhí)行仇矾,否則還要編譯成 OpCode 并緩存后才能執(zhí)行。

代碼執(zhí)行完成后解总,會將處理結果打印或著發(fā)送 HTTP 響應給客戶端贮匕,然后 PHP 底層代碼會執(zhí)行請求關閉及模塊關閉函數(shù)進行后續(xù)清理工作,最后再回到 SAPI 層花枫,調用 PHP-FPM 對應的關閉函數(shù)刻盐,從而完成此次請求的所有流程。

這個過程周而復始劳翰,每次用戶有新請求過來都會從頭執(zhí)行一遍敦锌,所有的環(huán)境初始化、模塊初始化佳簸、請求初始化以及 Laravel 應用的啟動過程乙墙,乃至后續(xù)請求關閉、模塊關閉生均、PHP-FPM 關閉听想,如果 Redis、MySQL 之類的網(wǎng)絡請求沒有連接池马胧,那么每次新請求過來汉买,所有的連接操作也要重新建立,所以傳統(tǒng)模式下的 PHP 應用性能表現(xiàn)一直為人所詬病佩脊,盡管 Nginx + PHP-FPM 模式已經大大優(yōu)于基于 Apache 運行的 PHP 應用了录别。

那我們能不能優(yōu)化這個請求處理流程呢?比如把環(huán)境初始化邻吞、模塊初始化组题、請求初始化、Laravel 應用的啟動過程只執(zhí)行一次抱冷,然后后面過來的請求復用上一次初始化的 PHP 環(huán)境崔列?此外,對于 Redis、MySQL 這些耗時的網(wǎng)絡連接以連接池的方式管理起來赵讯?事實上盈咳,基于 Swoole 就可以完成這些優(yōu)化,并且我們還可以基于其提供的協(xié)程功能實現(xiàn)并發(fā)編程边翼,使得在 PHP 中也可以輕松實現(xiàn)異步并發(fā)編程鱼响,不過關于 PHP 動態(tài)語言執(zhí)行時的性能優(yōu)化(邊解釋邊執(zhí)行)這一點需要 PHP 底層開發(fā)組去優(yōu)化,畢竟動態(tài)語言有利有弊组底,不可能又要性能丈积,又要編碼靈活性。

但是 Laravel 官方并沒有實現(xiàn)對 Swoole 的兼容和集成债鸡,所以我們需要自己實現(xiàn)在 Laravel 中集成 Swoole 進行編碼工作江滨,從而充分利用 Swoole 的異步編程、并發(fā)編程特性提升 Laravel 的性能厌均,但是如果想在 Laravel 中充分集成 Swoole 并不是一件輕松的工作唬滑,要考慮和測試的東西很多,好在現(xiàn)在已經有了可選的擴展包棺弊,業(yè)內比較有名的是 laravelslaravel-swoole晶密,基于它們提供的功能,我們可以輕松在 Laravel 中基于 Swoole 實現(xiàn)高性能編程模她。

為什么基于 Swoole 驅動的 Laravel 應用性能更好惹挟?
下面我們來看看基于 Swoole 驅動的 Laravel 應用從哪些方面對傳統(tǒng)的 PHP Web 請求處理流程進行了優(yōu)化。

laravels 擴展包為例缝驳,它為我們提供了一個內置的基于 Swoole 的 HTTP 服務器,通過php bin/laravels start 命令啟動归苍,Nginx 會將 PHP 請求都發(fā)到這個服務器進行處理用狱,與 PHP-FPM 不同的是,這個 Swoole 服務器啟動后拼弃,會開啟多個 Worker 進程夏伊,在每個 Worker 進程中,Laravel 應用啟動及之前的環(huán)境初始化工作只執(zhí)行一次吻氧,請求結束后溺忧,Laravel 應用實例不會回收,后續(xù)發(fā)給該 Worker 進程處理的請求會復用之前已經啟動的 Laravel 應用實例盯孙,再結合 MySQL鲁森、Redis 長連接,從而極大提高了 Laravel 應用的性能振惰。

在 Laravel 中使用 Swoole 的注意事項
單例模式
如上所述歌溉,Laravel 應用實例位于 Swoole 的 Worker 進程中,并且常駐內存,這種模式提升了應用性能的同時痛垛,也引入了新的復雜性草慧,因為 Laravel 底層的核心是一個Application IoC 容器,所有服務都綁定在這個容器里匙头,然后在應用的時候從里面解析漫谷,包括通過 singleton 方法以單例模式綁定的服務。

這在傳統(tǒng)的每次請求重新初始化新的 Application 容器的開發(fā)模式中當然沒有什么問題蹂析,但是現(xiàn)在問題來了舔示,單例模式綁定的服務在整個應用生命周期內解析時返回的都是同一個對象實例,現(xiàn)在這個生命周期延生到整個 Worker 進程的生命周期识窿,只要 Worker 進程還在斩郎,那么多個請求使用的可能都是同一個單例服務,這對不同請求可以復用單例的場景來說是好事喻频,比如數(shù)據(jù)庫連接缩宜,但是對另一些場景,不同請求不能復用同一個實例甥温,比如用戶認證锻煌,則是災難了,所以在這種場景下姻蚓,需要在一次請求完成后手動注銷這些單例服務(或者在下次實例化先判斷單例是否存在宋梧,如果存在將其銷毀)。

還是以laravels擴展包為例狰挡,它為我們提供的針對這種場景的解決方案是在每次請求處理完成后調用清理器對這些單例服務進行請求捂龄,你可以通過在 laravels 配置文件中注釋 cleaners 配置項來啟用這些清理器:

'cleaners' => [
    Hhxsv5\LaravelS\Illuminate\Cleaners\SessionCleaner::class, // If you use the session/authentication in your project, please uncomment this line
    Hhxsv5\LaravelS\Illuminate\Cleaners\AuthCleaner::class,    // If you use the authentication/passport in your project, please uncomment this line
    Hhxsv5\LaravelS\Illuminate\Cleaners\JWTCleaner::class,     // If you use the package "tymon/jwt-auth" in your project, please uncomment this line
    // ...
],

上面三個都是用戶認證相關的清理器,除此之外加叁,該擴展包還提供了針對 Request 和 Cookie 的清理器倦沧,可以去源碼中查看,如果你想要自定義清理器它匕,也可以仿照這些自帶的清理器實現(xiàn)來編寫實現(xiàn)了 Hhxsv5\LaravelS\Illuminate\Cleaners\CleanerInterface 接口的清理器類并將其配置到cleaners 配置項展融。

除了清理類之外,還可以像上面介紹的那樣豫柬,在中間件或者服務提供者中處理新請求時銷毀已存在的單例服務(laravels 配置文件中包含一個 register_providers 配置項告希,用于在每次請求處理時重新初始化服務綁定設置)。

同理烧给,通過static 定義的靜態(tài)變量也要在必要的時候進行清理燕偶,通過 global 定義的全局變量則要慎用,因為它會在同一個 Worker 進程處理的多個請求中復用础嫡。

exit/die 相關
由于 Swoole 中禁用 exit/die 函數(shù)杭跪,所以在 Laravel 中也不能使用它們,以及與之相關的 dd 函數(shù)。

from: https://laravelacademy.org/post/19832.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末涧尿,一起剝皮案震驚了整個濱河市系奉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌姑廉,老刑警劉巖缺亮,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異桥言,居然都是意外死亡萌踱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門号阿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來并鸵,“玉大人,你說我怎么就攤上這事扔涧≡暗#” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵枯夜,是天一觀的道長弯汰。 經常有香客問我,道長湖雹,這世上最難降的妖魔是什么咏闪? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮摔吏,結果婚禮上鸽嫂,老公的妹妹穿的比我還像新娘。我一直安慰自己征讲,他們只是感情好据某,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著稳诚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瀑踢。 梳的紋絲不亂的頭發(fā)上扳还,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音橱夭,去河邊找鬼氨距。 笑死,一個胖子當著我的面吹牛棘劣,可吹牛的內容都是我干的俏让。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼首昔!你這毒婦竟也來了寡喝?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤勒奇,失蹤者是張志新(化名)和其女友劉穎预鬓,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赊颠,經...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡格二,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了竣蹦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顶猜。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖痘括,靈堂內的尸體忽然破棺而出长窄,到底是詐尸還是另有隱情,我是刑警寧澤远寸,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布抄淑,位于F島的核電站,受9級特大地震影響驰后,放射性物質發(fā)生泄漏肆资。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一灶芝、第九天 我趴在偏房一處隱蔽的房頂上張望郑原。 院中可真熱鬧,春花似錦夜涕、人聲如沸犯犁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酸役。三九已至,卻和暖如春驾胆,著一層夾襖步出監(jiān)牢的瞬間涣澡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工丧诺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留入桂,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓驳阎,卻偏偏與公主長得像抗愁,于是被迫代替她去往敵國和親馁蒂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355