swoole之代码热更新实现
From:?http://www.th7.cn/Program/php/201405/211057.shtml
持續的思考:
?本人參與的swoole項目有幸被很多朋友使用,我也大力向周邊的一些朋友推薦,隨著swoole的版本迭代更新,已經足夠穩定了,在阿里,騰訊,yy等各大公司都有著使用,也有很多游戲圈里的朋友也在使用,這些朋友經常會提到一個問題,每次代碼更新還需要停止服務,然后重新啟動,來達到更新代碼,然而這種做法,是比較粗暴的。其實swoole里提供reload的特性,完全支持代碼的熱更新。
在介紹swoole的reload之前,先簡要的講講web方式是如何改了文件就立即生效的:
??幾個概念:
??1) sapi:可以簡單的理解為php引擎對外的一個統一接口,使得php可以和外部程序進行交互
??2) php的生命周期中關鍵四個調用:MINT -> RINT -> RSHUTDOWN -> MSHUTDOWN
??3) ?fpm : fastcgi進程管理器
??那么fpm方式的流程就是: fpm通過sapi接口與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進程。
簡單原理: 調用$server->reload()的時候:
??第一步: 向manager進程發送USR1信號,
??第二步: manager捕獲到USR1信號,會向worker進程發送 TERM信號。
??第三步:worker進程捕獲這個TERM信息,做把一個running的標識設置0
??第四步:woker的事件循環發現running標識為0,處理完當前邏輯就會自殺(自殺前會回調onWorkerStop函數),
??第五步:manager再拉起一個新的worker (拉起后會回調onWorkerStart函數)
?我們會發現,onWorkerStart 和 onWorkerStop非常像 sapi里的 RINT, RSHUTDOWN.
??所以到了這里,reload的方案就呼之欲出了:
??我們把業務邏輯的腳本代碼載入放到onWorkerStart里來。就行了。
示例:
?function onWorkerStart($serv,$worker_id) {
?????include"hot_update_class.php";
?????$class=newHotUpdate(); ?
?}
如果修改了hot_update_class.php里的相關文件,再執行$serv->reload(),就可以實現熱更新了。
如果你使用了autoloader, 那么你把autoloader的注冊放到onWorkerStart里來。
如果你使用了框架,那么你可以把框架的入口文件放到onWorkerStart里來。
如果你開啟了opcache,那么,你可以在onWorkerStop的時候,執行相關的opcache清理工作。
(zend_opcache,直接調用opcache_reset()方法即可)
?function onWorkerStop($serv,$worker_id) {
?????opcache_reset(); //zend_opcache的 ?????
?????//apc, xcache, eacc等其他方式,請調用相關函數 ?
?}
最后希望這篇博客能給你帶來一些幫助。(注:如果你的worker里掛了異步事件,比如把某個curl掛到swoole_event_add里,那么worker的reload會把這些都清理掉,可能導致一些邏輯錯誤,解決方案正在醞釀中)
swoole官方交流群:321637118
總結
以上是生活随笔為你收集整理的swoole之代码热更新实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ios-新浪微博-下拉刷新获取最新的消息
- 下一篇: 最全js表单验证