摘要:我們?yōu)榱颂幚磉@些挑戰(zhàn),提出了一個(gè)新的引用測試框架當(dāng)然,也是開源的,并且在整個(gè)過程中節(jié)省了上百萬美元。另一方面,被證實(shí)有一些嚴(yán)重的缺點(diǎn)部署困難而且慢。在緩存刷新期間,當(dāng)可用于別的進(jìn)程的已緩存的文件字節(jié)碼在此時(shí)損壞,就會(huì)導(dǎo)致崩潰。
How Badoo saved one million dollars switching to PHP7
我們成功的把我們的應(yīng)用遷移到了php7上面(數(shù)百臺(tái)機(jī)器的集群),而且運(yùn)行的很好,據(jù)說我們是第二個(gè)把如此規(guī)模的應(yīng)用切換到php7的企業(yè),在切換的過程我們發(fā)現(xiàn)了一些php7字節(jié)碼緩存的bug,慶幸的是這些bug現(xiàn)在已經(jīng)被修復(fù)了,現(xiàn)在我們把這個(gè)激動(dòng)人心的消息分享給所有的php社區(qū):php7現(xiàn)在已經(jīng)可以穩(wěn)定的運(yùn)行在商用環(huán)境上,而且比以前更加節(jié)省內(nèi)存,性能也有的很大的提高。
下面我會(huì)詳細(xì)的介紹下我們是如何把應(yīng)用前移動(dòng)php7的,我們在這中間遇到的問題及處理情況,還有最終的結(jié)果。但首先讓我們回頭看看一些更常見的問題:
Web項(xiàng)目的瓶頸在于數(shù)據(jù)庫持久化這是一個(gè)常見的誤解。一個(gè)設(shè)計(jì)良好的系統(tǒng)應(yīng)該是平衡的:當(dāng)訪問量增長時(shí),由系統(tǒng)的各個(gè)部分分?jǐn)傔@些壓力,同樣的,當(dāng)達(dá)到系統(tǒng)閥值時(shí),系統(tǒng)的所有組件(不僅僅包括硬盤數(shù)據(jù)庫,還有處理器和網(wǎng)絡(luò))共同分?jǐn)倝毫Α;谶@個(gè)事實(shí),應(yīng)用集群的處理能力才應(yīng)該是最重要的因素。在很多項(xiàng)目中,這種集群由數(shù)以百計(jì)甚至數(shù)以千計(jì)的服務(wù)器組成,這是因?yàn)榛〞r(shí)間去調(diào)整集群的處理能力更加經(jīng)濟(jì)實(shí)益(我們因此節(jié)省一百多萬)。
PHP的Web應(yīng)用,處理器的消耗跟其他動(dòng)態(tài)高級語言一樣多。但是PHP開發(fā)者面對著一個(gè)特別的障礙(這讓他們成為其他社區(qū)惡意攻擊的的受害者):缺少JIT,至少?zèng)]有一個(gè)像C/C++語言那樣的可編譯文本的生成器。PHP社區(qū)無力在核心項(xiàng)目框架上去實(shí)現(xiàn)一個(gè)類似的解決方案更是樹立了一種不良的風(fēng)氣:主要的開發(fā)成員開始整合他們的解決方案,所以HHVM在Facebook上誕生了,KPHP在VKontakte上誕生,還有其他類似的方案。幸運(yùn)地是,在2015年,隨著PHP7的正式發(fā)布,PHP要開始"Grow up"啦。雖然還是沒有JIT,但很難去評定這些改變在"engine"中有多重要。現(xiàn)在,盡管沒有JIT,PHP7可以跟HHVM相匹敵( Benchmarks from the LightSpeed blog or PHP devs benchmarks)。新的PHP7體系架構(gòu)將會(huì)讓JIT的實(shí)現(xiàn)變得簡單。
在Badoo的平臺(tái)開發(fā)者已經(jīng)非常關(guān)注近些年出現(xiàn)的每一次問題,包括HHVM試點(diǎn)項(xiàng)目,但是我們還是決定等待很有前途的PHP7的到來。現(xiàn)在我們啟動(dòng)了已經(jīng)基于PHP7的Baboo!這是一個(gè)史詩般的項(xiàng)目,擁有300多萬行的PHP代碼,并且經(jīng)歷了60000次的測試。我們?yōu)榱颂幚磉@些挑戰(zhàn),提出了一個(gè)新的PHP引用測試框架(當(dāng)然,也是開源的),并且在整個(gè)過程中節(jié)省了上百萬美元。
在切換到PHP7之前,我們曾花了不少時(shí)間來尋找優(yōu)化后端的方法。當(dāng)然,第一步就是從HHVM下手。在試驗(yàn)了幾周之后,我們獲得了值得關(guān)注的結(jié)果:在給框架中的JIT熱身之后,我們看到速度與CPU使用率上升了三倍。
另一方面,HHVM 被證實(shí)有一些嚴(yán)重的缺點(diǎn):
部署困難而且慢。在部署過程中,你不得不首先啟動(dòng)JIT-cache。當(dāng)機(jī)器啟動(dòng)的時(shí)候,它不能負(fù)載產(chǎn)品流量,因?yàn)樗械氖虑檫M(jìn)行的相當(dāng)慢。HHVM
團(tuán)隊(duì)同樣不推薦啟動(dòng)并行請求。順便一提,大量聚類操作在啟動(dòng)階段并不快速。此外,對于幾百個(gè)機(jī)器構(gòu)成的大集群你必須學(xué)習(xí)如何分批部署。這樣體系結(jié)構(gòu)和部署過程相當(dāng)繁瑣,而且很難估算出所需要的時(shí)間。對于我們來說,部署應(yīng)該盡可能簡單快捷。我們的開發(fā)者將在同一天提供兩個(gè)開發(fā)版并且釋出許多補(bǔ)丁。
測試不便。我們非常依賴runkit擴(kuò)展,但是它在HHVM中卻不可用。稍后我們將詳細(xì)介紹runkit,但是無需多言,它是一個(gè)能讓你幾乎隨心所欲更改變量、類、方法、函數(shù)行為的擴(kuò)展。這是通過一個(gè)抵達(dá)PHP核心的集成來實(shí)現(xiàn)的。HHVM引擎僅僅顯示了略微相像的PHP外觀,但是他們各自的核心十分不同。鑒
于擴(kuò)展的特定功能,在HHVM上獨(dú)立地實(shí)現(xiàn)runkit異常困難,而且我們不得不重寫數(shù)萬測試用例以確保HHVM和我們的代碼正確的工作。這看起來似乎不
值得。公平的說,我們以后在處理所有其他選項(xiàng)時(shí)也會(huì)遇到同樣的問題,而且我們在遷移到PHP7時(shí)仍然要重做許多事情包括擺脫runkit。但是以后會(huì)更多。
兼容性。主要問題是不完全兼容PHP5.5(參考此處)
,并且不兼容現(xiàn)有的擴(kuò)展(許多PHP5.5的)。這些所有的不兼容性導(dǎo)致了這個(gè)項(xiàng)目的明顯缺點(diǎn): HHVM
不是被大社區(qū)開發(fā)的,相反只是Facebook的一個(gè)分支。在這種情況下公司很容易不參考社區(qū)就修改內(nèi)部規(guī)則和標(biāo)準(zhǔn),而且大量的代碼包含其中。換句話說,
他們關(guān)起門來利用自己的資源解決了問題。因此,為了解決相似的問題,一個(gè)公司需要有Facebook一樣的資源不僅投入最初的實(shí)現(xiàn)同樣要投入后續(xù)支持。這
個(gè)提議不僅有風(fēng)險(xiǎn)而且可能開銷很大,所以我們決定拒絕它。
潛力。盡管Facebook是一個(gè)大公司而且擁有無數(shù)頂尖程序員,我們?nèi)匀粦岩伤麄兊腍HVM開發(fā)者比整個(gè)PHP社區(qū)更強(qiáng)。我們猜想PHP的類似于HHVM的東西會(huì)很快出現(xiàn),而前者將慢慢淡出我們的視野。
讓我們耐心等待PHP7。
切換到新版本的PHP7解釋器是一個(gè)重要和艱難的過程,我們準(zhǔn)備建立一個(gè)精確的計(jì)劃。這個(gè)計(jì)劃包括三個(gè)階段:
修改PHP構(gòu)建/部署的基礎(chǔ)設(shè)施和為大量的擴(kuò)展調(diào)整現(xiàn)有的code
改變基礎(chǔ)設(shè)施和測試環(huán)境
修改PHP應(yīng)用程序的代碼。
我們稍后會(huì)給出這些這些階段的細(xì)節(jié)。
引擎和擴(kuò)展的變化在Badoo中, 我們有積極的支持和更新的PHP分支,我們在PHP7正式版release之前我們就已經(jīng)開始切換到php7了. 所以我們不得不在我們的代碼樹經(jīng)常整合(reBase)PHP7上游的代碼,以便它來更新每個(gè)候選發(fā)布版。我們每天在工作中所用的補(bǔ)丁和自定義的code都需要在兩個(gè)版本之間進(jìn)行移植。
下載和構(gòu)建依賴庫、擴(kuò)展程序、還包括PHP 5.5和7.0的構(gòu)建這些過程都是自動(dòng)化的完成的。這不僅簡化了我們目前的工作,也預(yù)示著未來:在版本7.1出來時(shí), 也許這一切(解析引擎和擴(kuò)展等等)都已經(jīng)準(zhǔn)備到位了;
如上所述,我們將注意力轉(zhuǎn)向擴(kuò)展。我們提供超過70種擴(kuò)展,已經(jīng)比基于我們產(chǎn)品改寫的開源產(chǎn)品的半數(shù)還要多。
為了盡快能夠切換到它們,我們已經(jīng)決定開始同時(shí)進(jìn)展兩件事情。第一個(gè)是逐一重寫各個(gè)關(guān)鍵擴(kuò)展,包括blitz模板引擎,共享內(nèi)存/APCu中的數(shù)據(jù)緩存,pinba數(shù)據(jù)分析采集器,以及其他內(nèi)部服務(wù)的自定義擴(kuò)展(總的來說,我們已經(jīng)通過自己的力量完成大概20種擴(kuò)展的重寫了)。
第二個(gè)是積極的清理僅僅在架構(gòu)中那些非關(guān)鍵部分使用的擴(kuò)展,讓整個(gè)架構(gòu)更加簡潔。我們已經(jīng)迅速清理了11種擴(kuò)展,都是那些無足輕重的!
另外,我們也同那些維護(hù)主要開放擴(kuò)展的作者,一起積極地討論P(yáng)HP7的兼容性(特別感謝xdebug的開發(fā)者Derick Rethans)。
我們遲點(diǎn)將進(jìn)入更詳細(xì)的關(guān)于移植PHP7擴(kuò)展的技術(shù)細(xì)節(jié)。
開發(fā)者已經(jīng)對PHP7中的內(nèi)部API做了大量修改,意味著我們可以修改大量的擴(kuò)展代碼了。
下面是幾個(gè)最重要的變更:
zval * -> zval。在早期的版本中,zval一直為新變量來分配內(nèi)存,但是現(xiàn)在引入了棧。
char * ->
Zend_string。PHP7的引擎使用了更先進(jìn)的字符串緩存機(jī)制。理由是,當(dāng)字符串與自身的長度同時(shí)存儲(chǔ)時(shí),新的引擎可以將普通字符串完整的轉(zhuǎn)換為zend-string格式。
數(shù)組API的改變。zend_string作為key來使用,同時(shí)基于雙向鏈表的數(shù)組實(shí)現(xiàn)方法也被替代為普通的數(shù)組,需要強(qiáng)調(diào)的是,數(shù)組占用一個(gè)大的文件塊,而不是很多小的空間。
所有這些都可以從根本上減少小型內(nèi)存分配的數(shù)量,結(jié)果是,提高PHP引擎2%的速度。
我們能夠注意到,所有這些修改都至少需要改變所有的擴(kuò)展(即使不是完全重寫)。雖然我們可以依賴內(nèi)置擴(kuò)展的作者進(jìn)行必要的修改,我們也當(dāng)然有責(zé)任自己修改他們,雖然工作量很大。由于內(nèi)部API的修改,使得只修改一些代碼段變得簡單。
不幸的是,引入使代碼執(zhí)行速度提升的垃圾回收機(jī)制讓引擎變得更加復(fù)雜并且變得更加難以定位問題。涉及到OpCache的問題。在緩存刷新期間,當(dāng)可用于別的進(jìn)程的已緩存的文件字節(jié)碼在此時(shí)損壞,就會(huì)導(dǎo)致崩潰。這就是它從外部看起來的樣子(zend_string):使用方法名或者常量突然崩潰并且垃圾就會(huì)出現(xiàn)。
鑒于我們使用了大量的內(nèi)部擴(kuò)展,其中許多處理都是專門針對字符串的,我們懷疑這個(gè)問題與如何使用字符串在內(nèi)部擴(kuò)展有關(guān)。我們寫了大量的測試,并進(jìn)行了大量的實(shí)驗(yàn),但沒有得到我們預(yù)期的結(jié)果。最后,我們從PHP引擎開發(fā)人員 Dmitri Stogov 那里尋求了幫助。
他的第一個(gè)問題是“你有沒有清除緩存?”我們解釋說,事實(shí)上,我們每一次都在清除緩存。在這一點(diǎn)上,我們意識(shí)到這個(gè)問題并不在我們這里,而是opcache。我們很快就轉(zhuǎn)載了這一案例,這有助于我們在幾天內(nèi)回復(fù)并解決這個(gè)問題。在7.0.4版本,這個(gè)修復(fù)沒有出來,就不可能使php7進(jìn)入穩(wěn)定產(chǎn)品。
我們?yōu)槲覀冊贐adoo上做測試感到特別驕傲。我們部署服務(wù)器的PHP代碼到產(chǎn)品環(huán)境,每天兩次,每次部署包含20-50份任務(wù)量(我們使用功能分支Git和自動(dòng)化緊JIRA集成版本)。鑒于這種時(shí)間表和任務(wù)量,我們沒有辦法不選擇自動(dòng)測試。目前,我們大約有6萬個(gè)單元測試,約50%的覆蓋率,其運(yùn)行在云上,平均2-3分鐘(參見我們的文章了解更多)。除了單元測試,我們使用更高級別的自動(dòng)測試,集成和系統(tǒng)測試,并為網(wǎng)頁做了Selenium測試,為手機(jī)客戶端做了Calabash測試。作為一個(gè)整體,這使我們能夠迅速達(dá)成與結(jié)論有關(guān)的代碼,每個(gè)具體版本的質(zhì)量,并應(yīng)用相應(yīng)的解決方案。
切換到新版本的解釋器是一個(gè)充滿潛在問題的重大變化,所以所有測試工作都是極其重要的。為了弄清我們到底做了什么,以及我們?nèi)绾卧O(shè)法做到這一點(diǎn),讓我們來看看近幾年測試開發(fā)在Badoo上是如何演變的。
通常,當(dāng)我們開始考慮實(shí)施產(chǎn)品測試(或在某些情況下,已經(jīng)開始實(shí)施的話)時(shí),在測試過程中我們會(huì)發(fā)現(xiàn)他們的代碼“并沒有達(dá)到測試階段”。出于這個(gè)原因,在大多數(shù)情況下,開發(fā)者在寫代碼時(shí)要牢記,代碼的可測試性是很重要的。架構(gòu)師應(yīng)允許用單元測試去取代調(diào)用和外部依賴對象,以便代碼測試能與外部環(huán)境相隔離。當(dāng)然,毫無疑問這是一個(gè)備受憎恨的要求,很多程序員認(rèn)為寫“可測試性”的代碼是完全不可接受的。他們認(rèn)為,這些限制完全不顧“優(yōu)秀代碼”的標(biāo)準(zhǔn)而且通常不會(huì)取得成功。你能想象到,大量不按規(guī)則編寫的代碼,導(dǎo)致測試為了等“一個(gè)更好的時(shí)機(jī)”被延遲,或者通過運(yùn)行小型測試來滿足并且在測試結(jié)果被推遲,或?qū)嶒?yàn)者為了使自己運(yùn)行的小測試能夠通過,只做了能夠通過的那部分(也就是指測試沒有產(chǎn)生預(yù)期的結(jié)果)。
我并不是說我們公司是一個(gè)例外,從一開始,我們的項(xiàng)目也未執(zhí)行測試。因?yàn)橐廊挥袔仔写a在生產(chǎn)過程中正常運(yùn)作,帶來效益,所以正如文獻(xiàn)中建議的,如果只是為了運(yùn)行測試重寫代碼將是一件愚蠢的事情。那將占用太長的時(shí)間,花費(fèi)太多。
幸運(yùn)的是我們有一個(gè)很棒的工具來解決“未測試代碼”的大問題——runkit。當(dāng)腳本在運(yùn)行時(shí),這個(gè) PHP 擴(kuò)展允許你對方法、類及函數(shù)進(jìn)行增、刪、改的操作。此工具還有很多其它的功能但我們這里用不到它們。從 2005 年到 2008 年這個(gè)工具由 Sara Goleman(就職于 Facebook,有趣的是他在做 HHVM 方向的工作)開發(fā)和支持了多年。從 2008 年至今則由 Dmitri Zenovich (帶領(lǐng) Begun 和 Mail.ru 的測試部門)進(jìn)行維護(hù)。我們也對這個(gè)項(xiàng)目做了些許貢獻(xiàn)。
同時(shí),runkit 是一個(gè)非常危險(xiǎn)的擴(kuò)展,它允許你在使用它的腳本在運(yùn)行的時(shí)候?qū)ΤA俊⒑瘮?shù)及類進(jìn)行修改。就像是一個(gè)允許你在飛行中重建飛機(jī)的工具。runkit 有直達(dá) PHP “心臟”的權(quán)力,一個(gè)小錯(cuò)誤或缺陷就能讓一切毀掉,導(dǎo)致 PHP 失敗或者你要用很多時(shí)間來查找內(nèi)存泄漏或做一些底層的調(diào)試。盡管如此,這個(gè)工具對于我們的測試還是必要的:不需要做大的重構(gòu)來完成項(xiàng)目測試只能在程序運(yùn)行的時(shí)候改變代碼來實(shí)現(xiàn)。
但是在切換到PHP7的時(shí)候發(fā)現(xiàn)runkit帶來了很大麻煩,因?yàn)樗⒉恢С中碌陌姹尽N覀儺?dāng)然也可以在新版本中添加支持,但是從長遠(yuǎn)考慮,這看起來并不是最可靠的解決途徑。因此我們選擇了其他方法。
最適合的方法之一就是從runkit遷移到uopz。后者也是PHP的擴(kuò)展,有著(與runkit)類似的功能性,于2014年正式推出。我在Wamba的同事建議使用uopz,它將有很好的速度體驗(yàn)。順便說一下uopz的維護(hù)者就是Joe Watkins(First Beat Media公司,英國)。不幸的是我們遷移到uopz的測試程序無論怎樣都無法成功運(yùn)行。在某些地方總會(huì)發(fā)生致命的錯(cuò)誤,出現(xiàn)在段錯(cuò)誤中。我們提交了一些報(bào)告,但很遺憾他們并沒有動(dòng)作(e.g.https://github.com/krakjoe/uopz/issues/18)。為了解決這種困境而重寫測試程序的付出將會(huì)非常高昂,即使重寫了也很容易再次暴露出問題。
鑒于我們不得不重寫大量的代碼,而且還要依賴于runkit和uopz這種不知道有沒有問題的項(xiàng)目。很明顯,我們有了結(jié)論:我們應(yīng)該重寫我們的代碼,而且要盡可能獨(dú)立。我們也承諾將盡一切可能來避免今后發(fā)生類似的問題,即使我們最終切換到HHVM或任何類似的產(chǎn)品。最終我們做出來了自己的框架。
我們的系統(tǒng)名為“SoftMocks”,“soft”意思是純php實(shí)現(xiàn),未使用擴(kuò)展。該項(xiàng)目目前是一個(gè)開源的php庫。 SoftMocks不跟PHP引擎綁定,它是在運(yùn)行中動(dòng)態(tài)重寫代碼,功能類似于Go語言的AOP!框架。
以下功能在我們的代碼里已經(jīng)測試過:
override類方法
覆蓋函數(shù)執(zhí)行結(jié)果
更改全局常量或類常量的值
類新增方法
所有這些東西都是用runkit實(shí)現(xiàn)的。動(dòng)態(tài)修改代碼使項(xiàng)目臨時(shí)變更有了可能性。
我們沒有更多篇幅來討論關(guān)于SoftMocks的細(xì)節(jié),但我們計(jì)劃寫一篇關(guān)于這個(gè)主題的文章。 這里我們給出一些關(guān)鍵點(diǎn):
通過重寫中間函數(shù)來適配原有的用戶代碼。因此所有的包含操作將自動(dòng)被中間函數(shù)重寫。
在每一個(gè)用戶定義的方法內(nèi)都增加了是否有重寫的檢查。如果存在重寫,相應(yīng)的重寫代碼就會(huì)被執(zhí)行。
原來直接函數(shù)調(diào)用的方式將被通過中間函數(shù)調(diào)用的方式所替換;這樣內(nèi)嵌函數(shù)和用戶自定義函數(shù)都能被執(zhí)行到。
對中間函數(shù)的動(dòng)態(tài)調(diào)用將覆蓋代碼中變量的訪問權(quán)限
SoftMocks 可以和 Nikita Popov"s 的 PHP-Parser 配合: 這個(gè)庫不是很快(解析速度大概比token_get_all 慢15倍),但他的接口讓你繞過語法解析樹,并且包含了一個(gè)方便的API 用來處理不確定的語法結(jié)構(gòu)。
現(xiàn)在讓我們回到本文主題:切換到PHP 7.0版本。 當(dāng)我們通過SoftMocks把整個(gè)項(xiàng)切換過來后,我們依然有1000多個(gè)測試需要手動(dòng)處理。你可以說這還不算太差的結(jié)果,和我們在開始時(shí)提到的60000個(gè)測試相比的話。 和runkit相比,測試速度沒有下降,所以SoftMocks并沒有性能問題。 為了公平起見,我們認(rèn)為uopz 明顯的快很多。
盡管PHP7包含了許多新功能,但是仍然存在一些與老版本兼容的問題。首要的解決辦法是閱讀官方的移植文檔,之后我們會(huì)馬上明白如果不去修改現(xiàn)有代碼,我們將會(huì)面對的不僅僅是在生產(chǎn)環(huán)境中遇到致命的未知錯(cuò)誤并且由于升級后代碼的改變,我們無法在日志中查找到任何信息。這將會(huì)導(dǎo)致程序無法正常運(yùn)行。
Badoo中有許多PHP代碼倉庫,其中最大的有超過2百萬行代碼。此外,我們還使用PHP實(shí)現(xiàn)了很多功能,從網(wǎng)站業(yè)務(wù)邏輯到手機(jī)應(yīng)用后段再到集成測試和代碼部署。就目前來說,我們的情況很復(fù)雜,畢竟Badoo有很長的歷史,我們使用它已經(jīng)快十年了,最不幸的是仍然有采用PHP4的環(huán)境在運(yùn)行。在Badoo中,我們不推薦用‘just stare at it long enough’的方式來發(fā)現(xiàn)問題。一套所謂的"Brazilian"系統(tǒng)將代碼部署在生產(chǎn)環(huán)境,你需要等待直到它發(fā)生錯(cuò)誤,這很容易引發(fā)大面積用戶在使用中遇到業(yè)務(wù)上的錯(cuò)誤,使其不明原因。綜上所訴,我們開始尋找一種方法能自動(dòng)發(fā)現(xiàn)不兼容的地方。
最初,我們試圖用IDE的,這是開發(fā)者中很受歡迎,但不幸的是,他們要么不支持PHP7的語法和特征,要么沒有函數(shù)可以在代碼中找到所有的明顯的危險(xiǎn)的地方,發(fā)現(xiàn)所有明顯危險(xiǎn)的地方。進(jìn)行了一些研究(如谷歌搜索)后,我們決定嘗試php7mar工具,它是用PHP實(shí)現(xiàn)一個(gè)靜態(tài)代碼分析儀。這PHP7工具使用起來非常簡單,很快工程,并為您提供了一個(gè)文本文件。當(dāng)然,它不是萬能的; 找特別是精心隱藏的問題點(diǎn)。盡管如此,該實(shí)用程序幫助我們鏟除約 90%的問題,大大加快和簡化了準(zhǔn)備 PHP7 的代碼的過程。
對我們來說,最常遇到的和潛在危險(xiǎn)的問題是以下內(nèi)容:
在func_get_arg()以及func_get_args的行為變化()。在PHP的第5版本中,這些功能中的傳輸?shù)臅r(shí)刻返回參數(shù)值,但在七個(gè)版本發(fā)生這種情況的時(shí)刻時(shí)func_get_args()被調(diào)用。換句話說,如果函數(shù)內(nèi)func_get_args前參數(shù)變量的變化()被調(diào)用,則該代碼的行為可以由五個(gè)版本不同。同樣的事情發(fā)生時(shí),應(yīng)用程序的業(yè)務(wù)邏輯壞了,但并沒有什么在日志中。
間接訪問對象變量,屬性和方法。并再次,危險(xiǎn)在于,該行為可以更改“靜默”。對于那些尋找更多的信息,版本間的差異進(jìn)行了詳細(xì)的描述在這里。
使用保留類名。在PHP7,可以不再使用布爾,整型,浮點(diǎn),字符串,空,真假類名稱。,是的,我們有一個(gè)空的類。它的缺席實(shí)際上使事情變得更容易,但因?yàn)樗3?dǎo)致錯(cuò)誤。
使用引用許多潛在的問題的foreach結(jié)構(gòu)被發(fā)現(xiàn)了。由于我們試圖早不改變迭代數(shù)組中的foreach或雖在其內(nèi)部指針數(shù),幾乎所有的人都表現(xiàn)在版本5和7相同。
剩余的不兼容性的情況下也很少遇到了 (像 "e" 修飾符在正則表達(dá)式),或他們固定的一個(gè)簡單的替換 (例如,現(xiàn)在所有構(gòu)造函數(shù)應(yīng)該被命名為 __construct()。類名稱不允許使用)。
但是,我們即使在開始修復(fù)代碼之前,我們很擔(dān)心,一些開發(fā)商做一些必要的兼容性變化,其他人會(huì)繼續(xù)寫不符合 PHP7 的代碼。為了解決這一問題,我們把 pre-receive 鉤在已更改的文件 (換句話說,確保語法匹配 PHP7) 上執(zhí)行 php7-l 在每一個(gè) git 存儲(chǔ)庫中。這并不能保證不會(huì)有任何兼容性問題,但它不會(huì)清除主機(jī)問題。在其他情況下,開發(fā)人員只是不得不變得更加專注。除此之外,我們開始在 PHP7 上運(yùn)行的測試整個(gè)集并與 PHP5 的結(jié)果進(jìn)行了比較。
此外,開發(fā)者不允許使用任何PHP7的新功能,例如,我們沒有禁止老版本的預(yù)接收鉤子 php5 -l。這允許我們讓代碼兼容PHP5和PHP7。為什么這個(gè)很重要?因?yàn)槌藀hp代碼的問題之外,還有PHP7極其自身擴(kuò)展的一些潛在的問題(這些都可以證實(shí))。并且不幸的是,不是所有的問題都可以在測試環(huán)境中重現(xiàn)出來;有一些我們只在產(chǎn)品的大負(fù)載時(shí)才見過。
很明顯我們需要一種簡單快速的方法在任何數(shù)量以及類型的服務(wù)器上切換php版本。要啟用的話,所有指向CLI-interpreter的代碼路徑都替換成了 /local/php,相應(yīng)的,是/local/php5或者/local/php7。這樣的話,要在服務(wù)器上改變php版本,需要改變鏈接(為cli腳本操作設(shè)置原子操作是很重要的),停止php5-fpm,然后啟動(dòng)php7-fpm。在Nginx中,我們使用不同的端口為php-fpm和啟動(dòng)php5-fpm,php7-fom設(shè)置兩個(gè)不同的upstream,但我們不喜歡復(fù)雜的nginx配置。
在執(zhí)行完以上的清單后,我們接著在預(yù)發(fā)布環(huán)境運(yùn)行Selenium 測試,這個(gè)階段暴露更多我們早期沒注意到的問題。這些問題涉及到PHP代碼(比如,我們不再使用過期全局變量$HTTP_RAW_POST_DATA,取而代之是 file_get_contents(“php://input”))以及擴(kuò)展(這里存在各種不同類型的段錯(cuò)誤)。
修復(fù)完早期發(fā)現(xiàn)的問題和重寫單元測試(這個(gè)過程中我們也發(fā)現(xiàn)若干隱藏在解析器的BUG比如這里)后,進(jìn)入到我們稱為“隔離”發(fā)布階段。這個(gè)階段我們在一定數(shù)量的服務(wù)器上運(yùn)行新版PHP。一開始我們在每個(gè)主要PHP集群(Web后臺(tái),移動(dòng)APP后臺(tái),云平臺(tái))上只啟動(dòng)一個(gè)服務(wù),然后在沒有錯(cuò)誤出現(xiàn)情況下,一點(diǎn)一點(diǎn)增加服務(wù)數(shù)量。云平臺(tái)是第一個(gè)完全切換到PHP7的大集群,因?yàn)檫@個(gè)集群沒有php-fpm需求。 fpm 集群必須等到我們找到或者Dmitri Stogov修復(fù)了OpCache問題。之后,我們也會(huì)將fpm集群切換到PHP7。
現(xiàn)在看下結(jié)果,簡單的說,他們是非常出色的。在這里,你能看到響應(yīng)時(shí)間圖,包括內(nèi)存消耗和我們的最大的集群(包括263服務(wù)器)的處理器的使用情況,以及在 Prague 數(shù)據(jù)中心的移動(dòng)應(yīng)用后端的使用。
響應(yīng)時(shí)間分布:
RUsage (CPU 時(shí)間):
內(nèi)存使用:
CPU 加載 (%)-移動(dòng)后臺(tái)集群
這一切到位,處理時(shí)間減少了一半,從而提高整體響應(yīng)時(shí)間約40%,由于一定量的請求處理時(shí)間是花在與數(shù)據(jù)庫和守護(hù)進(jìn)程通信。從邏輯上講,我們不希望這部分加快切換到php7。除此之外,由于超線程技術(shù),集群的整體負(fù)載下降到50%以下,進(jìn)一步促進(jìn)了令人印象深刻的結(jié)果。廣義而言,當(dāng)負(fù)載增加超過50%,HT-engines,而不是作為有用的物理引擎開始工作。但這已經(jīng)是另一篇文章的主題。此外,記憶的使用,這從來沒有一個(gè)瓶頸,我們,減少了大約八倍以上!最后,我們節(jié)省了機(jī)器的數(shù)量。換句話說,服務(wù)器的數(shù)量可以承受更大的負(fù)載,從而降低獲取和維修設(shè)備的費(fèi)用。在剩余的聚類結(jié)果相似,除云上的收益是一個(gè)更溫和的(大約40%個(gè)CPU),由于opcache操作的減少。
來算算我們能節(jié)省多少費(fèi)用呢?大致測算一下,一個(gè)Badoo應(yīng)用服務(wù)器集群大概包含600多臺(tái)服務(wù)器。如果cpu使用率減半,我們可以節(jié)省大約300臺(tái)服務(wù)器。考慮服務(wù)器的硬件成本和折舊,每臺(tái)大約4000美元。總的算下來我們能節(jié)省大約100萬美元,另加每年10萬的主機(jī)托管費(fèi)。而且這還沒有計(jì)算對服務(wù)云性能的提升帶來的價(jià)值,這個(gè)結(jié)果很令人振奮。
另外,您是否也考慮切換到PHP 7.0版本呢? 我們很希望聽聽您關(guān)于此問題的觀點(diǎn),而且非常愿意在下面的評論中回答您的疑問。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/21427.html
摘要:內(nèi)部原本有多個(gè)基于的項(xiàng)目,但是在加入聯(lián)盟之后,這些項(xiàng)目不是被取消就是轉(zhuǎn)為基于繼續(xù)研發(fā),蔣清野表示不過的研發(fā)成果沒有能夠及時(shí)回饋到社區(qū)。但蔣清野表示,從目前開源生態(tài)系統(tǒng)的發(fā)展?fàn)顩r來看,斷定將成為的工業(yè)標(biāo)準(zhǔn),還為時(shí)過早。 在美國導(dǎo)航與控制公司工作期間,蔣清野與NASA有過一段協(xié)同合作,談到NASA發(fā)起的OpenStack自然有不少感悟。NASA早期選擇使用了Eucalyptus構(gòu)建自己的私有云,...
摘要:譯者按等待用戶反饋,一切都晚了實(shí)時(shí)監(jiān)控線上應(yīng)用才是王道。他們需要親自去發(fā)現(xiàn)問題的原因然后尋找解法,而不是依賴于用戶的截屏反饋。最終你會(huì)發(fā)現(xiàn)只有的用戶會(huì)反饋問題,然而事實(shí)上多得多。事后評估發(fā)現(xiàn)總共影響了名用戶,但是只收到個(gè)用戶反饋。 譯者按: 等待用戶反饋BUG,一切都晚了!實(shí)時(shí)監(jiān)控線上應(yīng)用才是王道。 原文: Why relying on your users to report err...
摘要:我們修改上面代碼,再來看下返回值類型限制的情況運(yùn)行結(jié)果這段代碼我們額外聲明了返回值的類型為型。對函數(shù)返回值的聲明做了擴(kuò)充,可以定義其返回值為,無論是否開啟嚴(yán)格模式,只要函數(shù)中有以外的其他語句都會(huì)報(bào)錯(cuò)。 順風(fēng)車運(yùn)營研發(fā)團(tuán)隊(duì) 王坤 發(fā)表至21CTO公眾號(hào)(https://mp.weixin.qq.com/s/ph...) showImg(https://segmentfault.c...
摘要:數(shù)據(jù)中心管理人員估計(jì),由于效率提高,每年可節(jié)省萬美元的運(yùn)營成本。更好的一點(diǎn)是,這種數(shù)據(jù)中心在兩周內(nèi)在現(xiàn)場部署,以幫助更快地實(shí)現(xiàn)成本的節(jié)省。如今,公共云的市場增長仍在持續(xù)。而根據(jù)媒體的報(bào)道,企業(yè)數(shù)據(jù)中心的待售數(shù)量比以往任何時(shí)候都要多。那么,人們真的正在目睹數(shù)據(jù)中心的消亡嗎?也許不是。隨著越來越多的企業(yè)將工作負(fù)載轉(zhuǎn)移到公共云中,可能會(huì)尋求出售他們的企業(yè)數(shù)據(jù)中心,而售后回租市場的激增則是一個(gè)很好的...
閱讀 3483·2021-11-18 10:02
閱讀 1612·2021-10-12 10:12
閱讀 2990·2021-10-09 09:53
閱讀 4858·2021-09-09 09:34
閱讀 847·2021-09-06 15:02
閱讀 2777·2021-08-05 10:02
閱讀 3134·2019-08-30 15:44
閱讀 3121·2019-08-28 18:04