軟件開發公司7種方式的PHP應用程序使用的長時間運行的操作優化
照片史葛比爾
今天我要談一談優化長期運行PHP操作基於(yú)較近的一個項目,我們已經成功地完成瞭(le)在這裏的可能途徑azoft Web開發部門我們的經驗将有助於(yú)Web開發人員想要順利工作的PHP應用程序即使任務是不斷發展變化的過程中。
本文沒有涵蓋所有可能的解決方案,它隻是旨在概述選項可以使用面對(duì)長(zhǎng)時間運行的操作 問題,節省你的時間。
項目概述
以下技術(shù)進(jìn)行項目:
MVC框架CakePHP 2.1(PHP5.3)
MySQL
jQuery
jQuery UI
jQuery插件
硒的服務器
CentOS
目标
的目标是開發瞭(le)一個原型一個系統的未來。事實上,這是一個試點項目,其規格和優先發展過程中經常改變(biàn)。因爲這個原因,它預測在早期階段,本項目系統将包含冗長的PHP操作相當困難。
問題
事實證明,這樣的操作導(dǎo)緻在後來的發(fā)展階段的一個主要挑戰:
這樣長(zhǎng)的操作阻塞其他操作在同一個(gè)會話。
通過系統鏈接導航整個過程變(biàn)得不可能直到長(zhǎng)操作完成。
有瞭(le)這些問題在一個較低的水平,我們發現,直到操作完成和會話數據刷新到會話文件因此消除堵塞,所有其他的要求必須在排隊(duì)耐心等待。
事實上,在PHP中存儲(chǔ)會話的默認方法是在一個文件中存儲(chǔ)。當(dāng)一個會話打開的功能,如fopen()被激活,阻斷閱讀和其他進程寫文件。
的時候,請求和導航通過鏈接被封鎖期間,用戶不知道發生瞭(le)什麽的那一刻,當操作就完瞭(le),是否有一些錯(cuò)誤。
解決這一問題的途徑
1。将操作步驟
第一個解決方案,可能會想到是将長(zhǎng)到短的操作步驟。當完成每一步並(bìng)将結果傳送到用戶的浏覽器,浏覽器會自動啓動下一步,發送相應的請求到服務器。
在上下文中的特定的項目,這種方法並(bìng)不成功,長期以來幾乎可分步驟操作。此外,在我們的項目中我們使用的第三方服務在服務器上運行,工作,需要創建和編(biān)寫相應的對象的請求處理期間。後處理的要求,通過對操作的第一步,該對象被殺。
2。Ajax輪詢
面對冗長的PHP操作的另一種方法是在服務器上啓動等操作不斷輪詢操作狀态更新服務器通過發送一系列的Ajax請求在一定的時間間隔。對於(yú)客戶端,我們可以分析服務器的響應(例如這可能是JSON的“消息”,含有“百分比”,“錯誤”和“重定向”)並(bìng)創建一個進度條,顯示當前操作的狀态。
在我們的項目中,我們嘗(cháng)試使用這種查詢方式採(cǎi)用兩種不同的方法來存儲和操作的結果:
在一個(gè)文件中存儲(chǔ)結果< > + <運行> session_id txt。
在相應的表格數據(jù)庫中存儲(chǔ)結果lengthy_operations
用戶開始運行Ajax請求。然後,客戶端腳本定期輪詢服務器並(bìng)接收到更新當(dāng)前操作:
view plaincopy to clipboardprint?
<trans data-src="/operations/get_status/">/操作/ get_status /</trans><operation_id></operation_id>
然而,在這裏我們遇到瞭(le)另一個問題:當冗長操作開始瞭(le)會議文件,從而消除瞭(le)處理並(bìng)發請求的可能性在同一會話。換句話說,在漫長的手術開始瞭(le),應該是被輪詢服務器必須在隊列中等待的主要要求是完成會話文件的請求。
爲瞭(le)解決這個問題,我們的目标是打開會話文件。爲瞭(le)做到這一點,我們利用瞭(le)一個PHP函數–session_write_close(),可以結束當前會話和存儲會話數據。事實上,它是可能的發射操作,讀取會話的數據,将數據更改,並(bìng)禁用寫會話文件權限。
然而,在實踐中,我們沒能爲我們做的這個項目。考慮到現有的架構,有必要在冗長(zhǎng)操作的地方太多的會議記錄。此外,這樣的解決方案不會被認爲是“幹(gàn)淨”的,因爲用戶可能想浏覽整個網站可能推出另一個耗時的操作在同一時間。因此,我們需要找到一個替代。
另一種是改變(biàn)會話存儲(chǔ),允許使用會話沒有阻止它在打開。在選擇一個新的會話存儲(chǔ),有幾個選項:
MySQL數據庫
MongoDB
memcached
爲瞭(le)在PHP會話存儲變化,有設置會話存儲–會話的用戶函數的特殊功能。save_handler()。這些用戶的功能是用於(yú)存儲和檢索數據,與會話相關聯的。事實上,功能save_handler()會話。可以用在許多不同的情況。有 甚至類可用於(yú)傳送會話到數據庫或緩存。
而工作對我們的項目,我們嘗(cháng)試用MySQL和MongoDB爲會話存儲(chǔ)。
注:讓我們說你記錄的參(cān)數到會話,你需要的是立即可用的其他要求。在這種情況下,你應該“沖洗”會話到MySQL或MongoDB,因此讓會議記錄工作。要做到這一點,你需要禁用編(biān)輯權限,然後重新打開它。
會話存儲(chǔ)改變(biàn)。無阻塞會話。
從(cóng)客戶端,Ajax請求開始啓動(dòng)運行。
一系列的輪詢請求來(lái)更新狀态和進(jìn)度條。
一個單(dān)獨的組件被創(chuàng)建的管理操作。
3。長輪詢
這種方法類似於(yú)Ajax輪詢,但有一個本質的區别。在Ajax輪詢,客戶端輪詢服務器發現如果發生任何變(biàn)化,但在長輪詢方式的服務器發送一個信号到客戶端時出現任何變(biàn)化。這是說,長輪詢方式需要服務器和客戶端之間的Cф穩定的網絡連接。這種方法的優點是減少客戶端和服務器之間的流量。
的工作原理。你可以這樣想:客戶端腳本調用服務器說,“如果數據出現,我就可以把它從(cóng)你的馬上,之後我再次與你聯系”。在一些服務器實現有緩沖(chōng)當服務器不給數據立即,等待,如果出現别的吧,我會把所有的數據一次”。然而,這樣的緩沖(chōng)是有害的因爲它導緻的延誤,我們想達到的較大速度!
浏覽器接收數據應該(gāi)再次打開新的連接之後。在理論上,這種連接可以持續幾個小時。但通常有更少的時間較多5分鍾之後,一個新的連接被創(chuàng)建。這樣做的原因是,服務器不喜歡持久的會議,和HTTP協議是不适合使用。
對(duì)於(yú)我們的項目在手,我們認爲這種方法但沒有結束使用它。
4。永遠(yuǎn)的iframe
我們(men)試著(zhe)用這種方法在我們(men)的項目。
的工作原理。首先,我們應該建立HTTP服務器和PHP,這樣他們就可以操作執行時發(fā)送數據的部分。然後創(chuàng)建一個隐藏的iframe标簽頁。标簽将逐步呈現的信息或執行操作的進展。
客戶(hù)端将使用iframe标簽初始化操作。在服務器端的操作将數據部分和立即發(fā)送到iframe執行發(fā)送響應客戶(hù)端的響應。
5。流
這是另一種方法,我們(men)嘗(cháng)試在我們(men)的項目。
這個想法是爲瞭(le)初始化操作通過Ajax請求,而服務器會在部分發(fā)送數據,即數據流。這樣,接收數據部分後,它可能是一些事件可能在客戶端發(fā)生。使用這樣的事件,我們可以更新相應的數據塊和數據加載顯示操作進度。
使用這種方法,首先我們需要在特定的方式設置Apache服務器、PHP。我們搜索瞭(le)關於(yú)網絡設置的信息和使用前進行一些測試。較後,設置如下:
然後我們寫瞭(le)一個(gè)組件,這種方法可能會使。
更詳細的分析結果證明這種方法是不适合我們的特定項目後。這是事實,有在客戶端可以對(duì)Ajax請求信号後接收數據的部分沒有事件,發(fā)送。這會在事件是在客戶端工作隻有數據是完全作爲一個整體。
6。彗星服務器
維基百科說,彗星是一個Web應用程序模型中,長(zhǎng)期持有的HTTP請求允許web服務器推送數據給浏覽器,浏覽器請求不明確(què)。
這種模型的一個共同的特點(diǎn),就是他們都不是基於(yú)專有插件,但通過浏覽器直接支持的技術,比如JavaScript。
在這個(gè)項目中我們測(cè)試的dklab realplexor Comet服務器。
下面是定義dklab realplexor将根據(jù)本項目的官方站點(diǎn)。
dklab realplexor是彗星的服務器可以處理1000000 +並(bìng)行長(zhǎng)期持有的HTTP連接用戶的浏覽器。在浏覽器中運行的JavaScript代碼在一個或幾個realplexor訂閱的渠道,建立一個數據接收處理程序。服務器可以在任何時候在這些渠道之一寫入消息。然後消息會立即傳遞給所有用戶–是否一個或在服務器上的較小負荷實時模式千。
7。WebSockets
我們還(hái)讨論瞭(le)使用WebSockets的可能性。
維基百科說,WebSocket是Web技術在一個(gè)TCP連接提供全雙工通信信道。它是用於(yú)浏覽器和Web服務器之間的實時信息交換。
但我們拒絕瞭(le)這個(gè)方法,它不是舊浏覽器的兼容。
總結
因此,我們解決的問題,採(cǎi)用輪詢的方法傳(chuán)遞會話MongoDB。
然而,進一步的讨論和在長(zhǎng)時間運行的任務以及它們的複雜性導緻瞭(le)更多的标準和可靠的解決方案的使用量的增加:用cron執行操作的隊列的實現(命令運行)。
事實上,在執行操作後檢查我們可以序列化operationcontext並(bìng)保存在數據庫中的所有權利:圖表cron_tasks。服務器将在特定的時間間隔運行的cron的外殼,這将從隊列中取下一個任務,改變(biàn)其狀态in_progress遞給随之而來的處理程序(taskdispatchercomponent)。該處理程序将序列化的任務上下文並(bìng)執行它在獨立的進程。請注意,處理程序可以訪問所有的系統模型和組件。
找出執行任務的進展,你可以使用Ajax輪詢和長輪詢,以及在一個單獨的顯示組織任務隊列的概述。這種方法已被
軟件開發公司證明是較可靠的和可以理解的,盡管它需要一些變化的系統架構。