你們都知道Swoole的性能在PHP界還算不錯,一樣都是PHP爲何呢,我專門研究了下。php
幾個概念:
1) sapi:能夠簡單的理解爲php引擎對外的一個統一接口,使得php能夠和外部程序進行交互
2) php的生命週期中關鍵四個調用:MINT -> RINT -> RSHUTDOWN -> MSHUTDOWN
3) fpm : fastcgi進程管理器
那麼fpm方式的流程就是: fpm經過sapi接口與php進程交互,也是普通PHP執行過程。
在fpm啓動的時候,
第一步: 會調用各擴展的MINT方法,進行一些數據初始化(長駐內存),
第二步: 每一個請求過來,先會執行RINT對單個請求行一個初始化,
第三步: 執行php腳本,
第四步: 執行RSHUTDOWN方法,
第五步: 若是你要中止fpm了,纔會執行MSHUTDOWN。
fpm對每一個請求的處理都是一直在在重複執行 2~4步 。
在第三步中, php的腳本是動態執行的,因爲每次都要執行一次php腳本,而每次php腳本都要有一個把php文件翻譯成opcode的流程(比較耗時), 因而就產生的opcache工具。
opcache: 直接把php翻譯後的opcode代碼樹保存到共享內存中,以便直接使用,從而減小每次都把php翻譯成opcode的開銷。
opcache的問題:按照他的描述,修改了php文件,並不能當即被更新,
opcache的解決方案:有一個配置來設置隔多長時間檢測文件是否更新了,從而有機會在第二步從新來reload相關的文件.
固然,你也能夠直接reload fpm,從而達到php熱更新的效果(opcache擴展能夠在第四步把相關的opcode cache給清空)。
swoole的問題:
swoole是以cli運行的,而後長駐內存的。整個生命週期只有在啓動的時間能夠一次執行RINT過程, 以後全部的請求都在第三步之內完成。(這也是swoole更快的緣由之一),這樣的話,相關的php腳本若是被執行了一次,就永久性的長駐內存了,更新代碼就沒有效果了。
swoole的解決方案:內置方法 $serv->reload()
前提:swoole是一個三層架構: master->manager->worker, master和manager是啓動以後,就長駐內存的,因此這裏reload的是worker進程,(而咱們的業務邏輯正好都在worker進程)。
簡單原理: 調用$server->reload()的時候:api
第一步: 向manager進程發送USR1信號,
第二步: manager捕獲到USR1信號,會向worker進程發送 TERM信號。
第三步:worker進程捕獲這個TERM信號,作把一個running的標識設置0
第四步:woker的事件循環發現running標識爲0,處理完當前邏輯就會自殺(自殺前會回調onWorkerStop函數),
第五步:manager再拉起一個新的worker (拉起後會回調onWorkerStart函數)
從這個流程中咱們會發現,onWorkerStart 和 onWorkerStop很是像 sapi裏的 RINT, RSHUTDOWN.swoole
這個問題參考了swoole熱更新的機制,guangla.com/post/swoole-reload,有興趣的同窗能夠看看。架構