PHP是最好的語言,Swoole重新定義了最好的語言,這當然是個梗了,不過php做為一個入門低、開發快、執行效率高的一門語言,而在以快速著稱的pc網際網路時代,無可爭議的成為首選,這是php的優勢,然後優勢慢慢轉化為思維定勢,在很多工程師看來php開發就等同於web開發,然而如今已經是移動互聯的時代,物聯網,智慧硬體也如火如塗,好像PHP不是那麼受待見了(ps:一直如此),而swoole的出現,成功突破了這一思維定勢,使phper可以從web開發跳出,進入了更大的伺服器網路程式設計領域,但web開發和伺服器網路程式設計在開發思維上還是有很大的不同,本系列文章將通過swoole的介紹,幫助大家做思維轉換,從而進入一個新天地。
PHP與SWOOLE的關係
swoole是php的一個擴充套件,純c開發,主要是為了補充php在網路程式設計方面的不足
PHP與SWOOLE的執行模式
php做為swoole的宿主,所以瞭解php本身的執行模式是必不可少的,下圖是以cli下執行一個php檔案時的完整流程
這上層有個SAPI的概念,SAPI是php給外部環境能夠執行php核心提供的一個統一介面,我們常見的三種SAPI有cli, php-fpm, mod_php。
在這裡,以fpm為例,把執行週期的關鍵5步拿出來:
1MINIT
在這步(包括之前)php引擎會初始化一些公用配置,讀取ini檔案,載入zend引擎,執行所以模組的MINIT模組,然後就長駐在fpm程式中,然後就等待處理請求
2RINIT
在每個請求過來之後,會呼叫所有模組的RINIT進行一些請求內資料的初始化,比如一些超全域性變數,一些模組資料初始化等
3執行php
然後在這載入php檔案,進行詞法,語法分析,生成opcode程式碼,交由zend vm執行, 暫存執行結果
4RSHUTDOWN
在把結果返回給fpm之前,會呼叫所有模組的RSHUTDOWN模組進行一些資料的回收,zend vm也會關閉開啟的資料流,進行記憶體釋放等操作,然後把暫存的執行結果flush輸出
5MSHUTDOWN
這一階段在重啟fpm時發生,會呼叫所有模組的MSHUTDOWN,關閉zend引擎等操作
到這,可以得到一些結論:
fpm每個請求都是在執行2~4步
opcode cache是把第3步的詞法分析、語法分析、生成opcode程式碼這幾個操作給快取起來了,從而達到加速的作用
幾個誤區:
1請求都是獨立的,不能進行資料共享? 其實還是有辦法進行在資料共享的,那就是在MINIT這步,因為這一步的資料是長駐在fpm程式中,比較典型的是ini配置檔案,我沒看過鳥哥新出的yaconf, 不過我猜測yaconf的配置讀取也應該是放在這一步進行
2每個請求都能獨立釋放記憶體, 所以總體是安全的。(這也是大多數phper沒有關閉資源的習慣,如mysql close等),那這也是有問題的,很有可能在擴充套件層有記憶體洩漏的存在,所以fpm提供max_reuqest來重啟fpm,達到完全釋放記憶體的目的,當然總體而言,php在記憶體控制方面還是相當不錯的。
OK, 我們分析出了php的基本流程,那swoole是在哪一步執行的呢?首先,swoole執行有個前提條件:必需在cli模式下執行. 然後在第3步,swoole就接管了php,進入了swoole的生命週期了。swooele的生命週期以多程式模式為例,如下:
1onStart
在回撥此函式之前Swoole Server已進行了如下操作
已建立了manager程式,已建立了worker子程式,已監聽所有TCP/UDP埠,已監聽了定時器
此函式是在主程式回撥的,和worker程式的onWorkStart是並行的沒有先後之分,在此回撥裡強烈要求只做log記錄,設定程式名操作,不做業務邏輯,否則業務邏輯程式碼的錯誤導致master程式crash,讓整個swoole server不對對外提供服務了。
2onWorkStart
每個worker或task程式在啟動之後,會回撥此函式,由於此回撥類似於fpm裡的MINIT,所以可以在這裡做一個全域性的資源載入,框架初始化之類的操作,這樣可以對每個請求做全域性共享,而達到提升效能的目的
3onReceive
每個請求(也稱資料到達),會回撥此函式,然後進行業務邏輯處理,輸出結果
4onWorkerStop
worker退出時,會回撥此函式。
5onShutDown
swoole服務停止回撥此函式,然後繼續fpm的第4、5步,進而退出PHP生命週期。