您的(de)位置: 北(běi)京軟件(jiàn)開(kāi)發公司 > 新聞動态 >
軟件(jiàn)開(kāi)發公司PHP應用(yòng)程序←Ω÷₹長(cháng)時(shí)間(jiān)使用(yòng)的(de)±" 操作(zuò)優化(huà)的(de)7種方§∞↓×式_北(běi)京軟件(jiàn)開(kāi€×÷&)發公司
發表日(rì)期:2015-08-31 15:36:46 文(wén)±♥章(zhāng)編輯:宜天信達 浏覽次數(shùλε>φ):
軟件(jiàn)開(kāi)發公司7種方式的(de)PHP應用(yòng)程序使用(yòng)的(d¥↕★e)長(cháng)時(shí)間(jiān)運行♠ £(xíng)的(de)操作(zuò)優化(huà)
照(zhào)片史葛比爾
今天我要(yào)談一(yī)談優化(huà)長(cháng)期運行(®≈xíng)PHP操作(zuò)基于較近(j← ≈ìn)的(de)一(yī)個(gè)項目,我們π♠已經成功地(dì)完成了(le)在這(zhè)裡(lǐ)的(de)÷"可(kě)能(néng)途徑azoft Web開(kāi)發部門(mén)我&♣Ω們的(de)經驗将有(yǒu)助于Web開(kāi)發人(rén)員(y±¶↔γuán)想要(yào)順利工(gōng)作(zuò)的(de)PHφ∞&✘P應用(yòng)程序即使任務是(shì)不(bù)斷發展變化(huà)的(↔∞ε de)過程中。
本文(wén)沒有(yǒu)涵蓋所有(y₹©ǒu)可(kě)能(néng)的(de)解決方案,它♦≠隻是(shì)旨在概述選項可(kě)以使用(y£♣≈òng)面對(duì)長(cháng)時(shí)間(jiān)運行(xíng®")的(de)操作(zuò) 問(wèn)題,節省你(nǐ)的(de)時(shΩ∑λ¥í)間(jiān)。
項目概述
以下(xià)技(jì)術(shù)進行(xíng)項目: π≤•;
MVC框架CakePHP 2.1(PHP5.3)
MySQL
jQuery
jQuery UI
jQuery插件(jiàn)
硒的(de)服務器(qì)
CentOS
目标
的(de)目标是(shì)開(kāi)發了(± >le)一(yī)個(gè)原型一(yī)個(gè)系統∑∞≠Ω的(de)未來(lái)。事(shì)實上(shàng)✔,這(zhè)是(shì)一(yī)個(gè)試點項目,其規格和(hé)$優先發展過程中經常改變。因為(wèi)這(zhè)個(gè↕ "★)原因,它預測在早期階段,本項目系統将包含冗長(cháng)的(de)PHP操∞≤作(zuò)相(xiàng)當困難。
問(wèn)題
事(shì)實證明(míng),這(zhè☆∑)樣的(de)操作(zuò)導緻在後來(lái)的(de)發展階段的(Ω☆<de)一(yī)個(gè)主要(yào)挑戰:
這(zhè)樣長(cháng)的(de)操作(zuò)阻塞其他(tā)操作(≈σ♥zuò)在同一(yī)個(gè)會(huì ≥)話(huà)。
通(tōng)過系統鏈接導航整個(gè)過₩γ程變得(de)不(bù)可(kě)能(nεεéng)直到(dào)長(cháng)操作(zu≈&★'ò)完成。
有(yǒu)了(le)這(zhè)些(xiē)問(wèn₽↓★)題在一(yī)個(gè)較低(dī)的(de¥αγ≥)水(shuǐ)平,我們發現(xiàn),直到(dào)操作(zu♣Ωφò)完成和(hé)會(huì)話(huà)數(shù)據±→®刷新到(dào)會(huì)話(huà)文(wén)件(jiàn)因此消除堵 ∑塞,所有(yǒu)其他(tā)的(de)要(yào)求必須在排隊§≠耐心等待。
事(shì)實上(shàng),在PHP中存儲會(huì)ε↕™•話(huà)的(de)默認方法是(shì)在一(y ><ī)個(gè)文(wén)件(jiàn)中存儲。當一(yī) 個(gè)會(huì)話(huà)打開(kā∏ ↓i)的(de)功能(néng),如(rú)fopen()被激活,阻斷閱讀(d¥↔ ú)和(hé)其他(tā)進程寫文(wén)件(jiàn∑★ )。
的(de)時(shí)候,請(qǐng)求和(hé)導航通(t←•ōng)過鏈接被封鎖期間(jiān),用(yò ±≠₩ng)戶不(bù)知(zhī)道(dào)發生(→βshēng)了(le)什(shén)麽的(d¥✘e)那(nà)一(yī)刻,當操作(zuò)就(jiù)完β→←了(le),是(shì)否有(yǒu)一(yī)些(xi☆εē)錯(cuò)誤。
解決這(zhè)一(yī)問(wèn)題的(de)σ×Ω♣途徑
1。将操作(zuò)步驟
第一(yī)個(gè)解決方案,可(kě)能(néng)會(huì)想到(d¥ε¶≤ào)是(shì)将長(cháng)到(dà>÷o)短(duǎn)的(de)操作(zuò)步驟。當 <完成每一(yī)步并将結果傳送到(dào)用(yòng)戶的(de)®₹浏覽器(qì),浏覽器(qì)會(huì)自(zì)動啓動下δ§(xià)一(yī)步,發送相(xiàng)應的(de)請(qǐng)÷©'求到(dào)服務器(qì)。
在上(shàng)下(xià)文(wén)中 α ☆的(de)特定的(de)項目,這(zhè)種方法并不(bù)成♣©©功,長(cháng)期以來(lái)幾乎可(kě)分(fē♥÷n)步驟操作(zuò)。此外(wài),在我們的(de)項目¶™≈中我們使用(yòng)的(de)第三方服務在服務器(₽→¥qì)上(shàng)運行(xíng),工(gōng)作(zuò),需要✘(yào)創建和(hé)編寫相(xiàngβ♦✔)應的(de)對(duì)象的(de)請(qǐng)求處理(lǐ♥)期間(jiān)。後處理(lǐ)的(deδ§)要(yào)求,通(tōng)過對(duì)操作≤∏•(zuò)的(de)第一(yī)步,該對(duì)象≤☆ε被殺。
2。Ajax輪詢
面對(duì)冗長(cháng)的(de)PHP操作(zuò)的(d✘®e)另一(yī)種方法是(shì)在服務器(qì)上(s↔<↓δhàng)啓動等操作(zuò)不(bù)斷輪詢φ×操作(zuò)狀态更新服務器(qì)通(tōng)過發送一(yī) ♣系列的(de)Ajax請(qǐng)求在一(yī)定的(de)時(s ♥hí)間(jiān)間(jiān)隔。對(↑λ☆λduì)于客戶端,我們可(kě)以分(fēn÷ > )析服務器(qì)的(de)響應(例如(rú)這('♦zhè)可(kě)能(néng)是(shì)JSON的(de)&ld≠quo;消息”,含有(yǒu)“百分(fēn)₽'≠≈比”,“錯(cuò)誤”和(hé)&l∑>→dquo;重定向”)并創建一(yī♦§≠↑)個(gè)進度條,顯示當前操作(zuò)的(de)狀态。
在我們的(de)項目中,我們嘗試使用(yòng)這(zhè)種查詢方式采♣"←用(yòng)兩種不(bù)同的(de)方法來® (lái)存儲和(hé)操作(zuò)的(de)結果:
在一(yī)個(gè)文(wén)件(jiàn)中存儲結果< >€€; + <運行(xíng)> session_id±☆ txt。
在相(xiàng)應的(de)表格數(sh•±ù)據庫中存儲結果lengthy_ope ♠≈rations
用(yòng)戶開(kāi)始運行(xíng)Aja₹σ÷x請(qǐng)求。然後,客戶端腳本定期輪詢服務器(qì)✘¥并接收到(dào)更新當前操作(zuò):
view plaincopy to clipboar₩✘dprint?
<trans data-src="/operaπ☆€tions/get_status/">≠Ω§ε;/操作(zuò)/ get_status /</tran↓ ¶s><operation_id></oper™ation_id>
然而,在這(zhè)裡(lǐ)我們遇到(dào)了(Ω≥₽'le)另一(yī)個(gè)問(wèn)題:當冗長(cháδ©λ∞ng)操作(zuò)開(kāi)始了(le)會(huì)議(yì)文(∞§∏δwén)件(jiàn),從(cóng)而✘♥$消除了(le)處理(lǐ)并發請(qǐng)求的(de)可(kě)能$↕ (néng)性在同一(yī)會(huì)話(huà)。換句☆©δ話(huà)說(shuō),在漫長(cháng)的(de)手術(shλ♠ù)開(kāi)始了(le),應該是(shì)被輪詢服 ×β©務器(qì)必須在隊列中等待的(de)主要'λλ↔(yào)要(yào)求是(shì)完成₹會(huì)話(huà)文(wén)件(jiàn)的(de₩∞¶)請(qǐng)求。
為(wèi)了(le)解決這(zhè)個(gè)問(®wèn)題,我們的(de)目标是(shì)打開λ"→δ(kāi)會(huì)話(huà)文(wén)φλ件(jiàn)。為(wèi)了(le)做(zuò✔)到(dào)這(zhè)一(yī)點,我們利用(yòng)了(le≥★∞)一(yī)個(gè)PHP函數(shù)–s≥φession_write_close(), λσ可(kě)以結束當前會(huì)話(huà)和(hé)存儲會(huì)話(±♦huà)數(shù)據。事(shì)實上(shàng),它是(shì)可(γkě)能(néng)的(de)發射操作(zuòσ♠∞÷),讀(dú)取會(huì)話(huà)的(de)≤±數(shù)據,将數(shù)據更改,并禁用(yòng)寫會(huì)÷δφ話(huà)文(wén)件(jiàn)權限。
然而,在實踐中,我們沒能(néng)為(wèi)我們做(zuò)的(d♦δ≤e)這(zhè)個(gè)項目。考慮到(dào)現(xi<☆>βàn)有(yǒu)的(de)架構,有(yǒu)必要(yào)在冗長(chá₽"πng)操作(zuò)的(de)地(dì)方太多(duō)的(de)會(→∏♦huì)議(yì)記錄。此外(wài),這(zhè)樣∑€的(de)解決方案不(bù)會(huì)被認為(wèi)是(shì)&ldq≠₩uo;幹淨”的(de),因為(wèi)用(y₹ ÷òng)戶可(kě)能(néng)想浏覽整個(gè)網站(zhàn)可₩₹₽<(kě)能(néng)推出另一(yī)個(gè)耗時(shí λ↑)的(de)操作(zuò)在同一(yī)時(shí)間(jiān)。因此,我βδ們需要(yào)找到(dào)一(yī)個(gè)替代。
另一(yī)種是(shì)改變會(huì)話(↓×huà)存儲,允許使用(yòng)會(huì)話(huà)沒₽∑"有(yǒu)阻止它在打開(kāi)。在選擇一(yī)個(≥↑™≈gè)新的(de)會(huì)話(huà)存"£ 儲,有(yǒu)幾個(gè)選項:
MySQL數(shù)據庫
MongoDB
memcached
為(wèi)了(le)在PHP會(huì)話(huà)存儲變化(hu>€ε≈à),有(yǒu)設置會(huì)話(huà)存儲–會₩£(huì)話(huà)的(de)用(yòng)戶函數(shù)$的(de)特殊功能(néng)。save_handler()。這(zhè)些(£←δ&xiē)用(yòng)戶的(de)功能(néng)是(shì)§δ>用(yòng)于存儲和(hé)檢索數(shù)據,與會(¥✔&÷huì)話(huà)相(xiàng)關聯的(dβ↑βe)。事(shì)實上(shàng),功能(néng)sav↓φ¥e_handler()會(huì)話(huà)。可(kě)以用(yò∑♣ng)在許多(duō)不(bù)同的(d₹±φ♣e)情況。有(yǒu) 甚至類可(kě)用(yòng)于傳送會(hu•™∞ì)話(huà)到(dào)數(shù)據庫或緩存π€±。
而工(gōng)作(zuò)對(duì)我們的(de)↕ 項目,我們嘗試用(yòng)MySQL和(hé)MongoDB為(≠¶ ♠wèi)會(huì)話(huà)存儲。
注:讓我們說(shuō)你(nǐ)記錄的♠♥±(de)參數(shù)到(dào)會(huì)≠δ≥話(huà),你(nǐ)需要(yào)的(de)是(shì) ±立即可(kě)用(yòng)的(de)其他(tā)≤★¥要(yào)求。在這(zhè)種情況下(xià)∞≤,你(nǐ)應該“沖洗&rdq™•uo;會(huì)話(huà)到(dào↕☆)MySQL或MongoDB,因此讓會(huì© ♥)議(yì)記錄工(gōng)作(zuò)。要(yào)做(zuò)到(d♦ ₹ào)這(zhè)一(yī)點,你(nǐ)需要(yào)禁用(yòng)編輯♦¶'權限,然後重新打開(kāi)它。
會(huì)話(huà)存儲改變。無阻塞會(huì)話(huà)↑¥。
從(cóng)客戶端,Ajax請(qǐng)求開(kāi)始啓動運行≥✔(xíng)。
一(yī)系列的(de)輪詢請(qǐng)求來(lái)更新狀态和(h♦≤é)進度條。
一(yī)個(gè)單獨的(de)組件(€↑§jiàn)被創建的(de)管理(lǐ)操作(zu∏¶ò)。
3。長(cháng)輪詢
這(zhè)種方法類似于Ajax輪詢,但(dàn)有(yǒu)一(yī)★≤個(gè)本質的(de)區(qū)别。在Ajax輪詢,客戶端輪詢服務器(q©♠ì)發現(xiàn)如(rú)果發生(shēng)任>∏何變化(huà),但(dàn)在長(cháng)輪詢方式的(d©↓®♥e)服務器(qì)發送一(yī)個(gè)信号到(dào)客 ✔↔∏戶端時(shí)出現(xiàn)任何變化(huà)。這±★♦€(zhè)是(shì)說(shuō),長(cháng)輪₽÷☆詢方式需要(yào)服務器(qì)和(hé)客戶端之間(jiān)的¥♦δ(de)Cф穩定的(de)網絡連接。這(zhè)¶&種方法的(de)優點是(shì)減少(sβ✔hǎo)客戶端和(hé)服務器(qì)之間 →→(jiān)的(de)流量。
的(de)工(gōng)作(zuò)原理(lǐ)。你(nǐ)可(kě)以這($§"zhè)樣想:客戶端腳本調用(yòng)服務器(qì)說(shu♣&ō),“如(rú)果數(shù)據出現(xiàn),我就(¶™Ωjiù)可(kě)以把它從(cóng)你(nǐ)的(dε♦e)馬上(shàng),之後我再次與你(nǐ)聯系”。在一•α↔(yī)些(xiē)服務器(qì)實現(xiàn)有(yǒu)®∑Ω緩沖當服務器(qì)不(bù)給數(shù)據立即,等待σ✔,如(rú)果出現(xiàn)别的(de)吧(☆™$ba),我會(huì)把所有(yǒu)的(de)™>©¶數(shù)據一(yī)次”。然而,Ω←<這(zhè)樣的(de)緩沖是(shì)有(yǒu)害的(de)因×→φ為(wèi)它導緻的(de)延誤,我們想達到(dào)的(de)較大(♠γεdà)速度!
浏覽器(qì)接收數(shù)據應該再次打開(kā✔♥↕i)新的(de)連接之後。在理(lǐ)論上(shàng),這(zhè)種連接可☆ β(kě)以持續幾個(gè)小(xiǎo)時(shí)。但(dà↓±n)通(tōng)常有(yǒu)更少(sh±™≈ǎo)的(de)時(shí)間(jiān)較多(duō)5分¶✘↕(fēn)鐘(zhōng)之後,一(yī)個(₽σgè)新的(de)連接被創建。這(zhè)樣做(zuò)的(de∑±)原因是(shì),服務器(qì)不(bù)喜歡持久的(de)會(huì)議(α∑yì),和(hé)HTTP協議(yì)是(shì)ε✔不(bù)适合使用(yòng)。
對(duì)于我們的(de)項目在手,我們認為(wèi)✘∑ ¥這(zhè)種方法但(dàn)沒有(yǒu)結束使用(yòng)它≈→±。
4。永遠(yuǎn)的(de)iframe
我們試著(zhe)用(yòng)這(zhè)↔∑ε種方法在我們的(de)項目。
的(de)工(gōng)作(zuò)原理(←βlǐ)。首先,我們應該建立HTTP服務器(qì)和(hé)P £HP,這(zhè)樣他(tā)們就(jiù)可(kě)以操作(z×α"uò)執行(xíng)時(shí)發送數(shù)據的(de)部分(fφ'¶ēn)。然後創建一(yī)個(gè)隐藏的(de)iframe标簽頁。标簽♣¶∑≤将逐步呈現(xiàn)的(de)信息或執行(xíng)操作(©×©$zuò)的(de)進展。
客戶端将使用(yòng)iframe标簽初始化(huàε≤∏→)操作(zuò)。在服務器(qì)端的(de↓)操作(zuò)将數(shù)據部分(fēn)和(hé)立即發送到(dào)÷∏iframe執行(xíng)發送響應客戶端的(de)響φ≠應。
5。流
這(zhè)是(shì)另一(yī)種方法,≠© ∏我們嘗試在我們的(de)項目。
這(zhè)個(gè)想法是(shì)為(wèi↑)了(le)初始化(huà)操作(zuò)通(tō<© ng)過Ajax請(qǐng)求,而服務器(qì)會(hu₩₩ì)在部分(fēn)發送數(shù)據,即數(shù)據流。這(z↓±'hè)樣,接收數(shù)據部分(fēn)後,它可(φ↑kě)能(néng)是(shì)一(yī)些(xiē)≠σ事(shì)件(jiàn)可(kě)能(₽∞$néng)在客戶端發生(shēng)。使用(yòng)這(zh¥↓וè)樣的(de)事(shì)件(jiàn),我們'∏<可(kě)以更新相(xiàng)應的(de)數(shù)據塊和(♠≈hé)數(shù)據加載顯示操作(zuò)進度。
使用(yòng)這(zhè)種方法,首先我們需要(yào)在特定≠的(de)方式設置Apache服務器(qì)、PHP。我們÷↑ 搜索了(le)關于網絡設置的(de)信息和(hé)使用(yòng)前進行("δxíng)一(yī)些(xiē)測試。較'φα後,設置如(rú)下(xià):
然後我們寫了(le)一(yī)個(gè)組件(jiàn),這(zhè)種€ 方法可(kě)能(néng)會(huì)使。
更詳細的(de)分(fēn)析結果證明§♦₹(míng)這(zhè)種方法是(shì)不(bσ®ù)适合我們的(de)特定項目後。這(zhè)是(shì)事(shì)實,有(<•♥yǒu)在客戶端可(kě)以對(duì)Ajaφ♥x請(qǐng)求信号後接收數(shù)據的(®λφde)部分(fēn)沒有(yǒu)事(shì)件(jiàn),發送™¶。這(zhè)會(huì)在事(shì)件(ji↓→àn)是(shì)在客戶端工(gōng)作(zuò)隻有(yǒu)數(shù★σ)據是(shì)完全作(zuò)為(wèi)一(yī)個(gè)整體(tǐγ§ β)。
6。彗星服務器(qì)
維基百科(kē)說(shuō),彗星是(shì)一(yī)個(gè)Wσ¶ Ωeb應用(yòng)程序模型中,長(cháng)期持有(yǒu)的(de₽< ')HTTP請(qǐng)求允許web服務器(qì)推送'•數(shù)據給浏覽器(qì),浏覽器(qì)請(qǐng)求不(↔ ₽bù)明(míng)确。
這(zhè)種模型的(de)一(yī)個(gè)共☆ 同的(de)特點,就(jiù)是(shì₹'<✘)他(tā)們都(dōu)不(bù)是(shì)基于專有(yǒu)插件(j&iàn),但(dàn)通(tōng)過浏πδ≈覽器(qì)直接支持的(de)技(jì)γ≈γ↔術(shù),比如(rú)JavaScript。
在這(zhè)個(gè)項目中我們測試的(de)dklab realpl<≥exor Comet服務器(qì)。
下(xià)面是(shì)定義dklab realpl"☆∏σexor将根據本項目的(de)官方站(zhàn)點。
dklab realplexor是(shì÷$)彗星的(de)服務器(qì)可(kě)以處理(lǐ)1000000 ↔φ ±+并行(xíng)長(cháng)期持有(yǒu)的(de)HTTΩ↕←↑P連接用(yòng)戶的(de)浏覽器(qì)"®≥。在浏覽器(qì)中運行(xíng)的(¥€✔de)JavaScript代碼在一(yī)個(∞ ♠εgè)或幾個(gè)realplexor訂閱的(de)↕<₽渠道(dào),建立一(yī)個(gè)數(shù)據接收處理(lǐ)程序。★<服務器(qì)可(kě)以在任何時(shí)候在這(zhè)些(xiē)✔δ¶渠道(dào)之一(yī)寫入消息。然後消息會(huì)立即傳遞給所₽γ有(yǒu)用(yòng)戶&ndash←®©";是(shì)否一(yī)個(gè)或在服務≠&≠Ω器(qì)上(shàng)的(de)較小(xiǎo)負荷實時(shβ♦í)模式千。
7。WebSockets
我們還(hái)討(tǎo)論了(le)使用(yòng)Web↔♥ ≤Sockets的(de)可(kě)能(néng)÷∑®性。
維基百科(kē)說(shuō),WebSocket是(shì ••)Web技(jì)術(shù)在一(yī)個(gè)TCP★±±連接提供全雙工(gōng)通(tōng)信¶¶₹信道(dào)。它是(shì)用(yòng)于α→σ浏覽器(qì)和(hé)Web服務器(qì)之間(jiān)的(de)實時(sλ₩∏hí)信息交換。
但(dàn)我們拒絕了(le)這(zhè)個(gè)方法,它不(£✔≠bù)是(shì)舊(jiù)浏覽器(qì)的(de<∞σ¶)兼容。
總結
因此,我們解決的(de)問(wèn)題,采用(yò★εng)輪詢的(de)方法傳遞會(huì)話(huà)M<$ongoDB。
然而,進一(yī)步的(de)討(tǎo)論和(hé)在長γΩφ₹(cháng)時(shí)間(jiān)運行(xíng)的(de)任務→♣ <以及它們的(de)複雜(zá)性導緻了(l♠Ωe)更多(duō)的(de)标準和(hé)可(kě)←♠≥靠的(de)解決方案的(de)使用(yòng)量的(de)增加:用(yòng)®→™✘cron執行(xíng)操作(zuò)的(de)隊列的(de)實σ→現(xiàn)(命令運行(xíng))。
事(shì)實上(shàng),在執行(xíng)操作(zuò)後檢查我們可λ∑♥(kě)以序列化(huà)operationc>÷ontext并保存在數(shù)據庫中的÷$ (de)所有(yǒu)權利:圖表cron_tasks。服務器(qì)≤γ↔α将在特定的(de)時(shí)間(jiān)間(jiān)隔運行(xíng≥β→ )的(de)cron的(de)外(wài)殼,這(zhè)将從(có¶≠λng)隊列中取下(xià)一(yī)個(gè)任務,±'φ¶改變其狀态in_progress遞給随之而來(lá¶×✘i)的(de)處理(lǐ)程序(taskd↑↓$♠ispatchercomponent)。該處理β©♣↓(lǐ)程序将序列化(huà)的(de)任務上(shàng)下(xiσ"à)文(wén)并執行(xíng)它在獨立的(de)進程。請(qǐng)注意,÷↔✘♥處理(lǐ)程序可(kě)以訪問(wèn)所有(∑✘yǒu)的(de)系統模型和(hé)組件(j↕ ₹≈iàn)。
找出執行(xíng)任務的(de)進展,你(nǐ)可(kě)以使用('♥♠yòng)Ajax輪詢和(hé)長(cháng)輪詢,以及在一(yī)₹ε個(gè)單獨的(de)顯示組織任務隊列的(de)概述。這(zhè β♥)種方法已被軟件(jiàn)開(kāi)發公司證明(míng)是(shì)較可(kě)靠的(de)αλ&和(hé)可(kě)以理(lǐ)解的(de↑©₽σ),盡管它需要(yào)一(yī)些(xiē)變化(÷αhuà)的(de)系統架構。