2014-01-17 130 views
0

我有一個名稱查找框,通過您的典型ajax請求操作。下面是每次按下字母時都會觸發的Javascript的一般流程:停止請求服務器端

  • 如果ajax請求已打開,則中止它。
  • 如果超時已經創建,請將其銷燬。
  • 設置新的超時運行以下在半秒:通過AJAX
  • 發送字符串「nameLookup.php」
  • 等待迴應
  • 顯示效果

的問題是,nameLookup .php是非常重要的資源。在某些情況下,多達10,000個名字正在從SQL數據庫中提取,解密並與字符串進行比較。在正常情況下,請求可能需要5到60秒才能返回。

我完全明白,當您在客戶端中止請求時,服務器仍在處理事件併發回結果。只是客戶端知道忽略響應。但是服務器在處理所有這些請求時變得如此懸而未決。

所以,如果你這樣做:

  • 請求1個
  • 中止請求1
  • 請求2
  • 中止請求2
  • 要求3
  • 等待請求響應3

服務器甚至沒有在請求3上工作,直到它完成1和2 ...或者它只是在請求1和2上工作,以致請求3需要額外的很長時間。

我需要知道如何告訴服務器停止對請求1和2的工作,所以我可以騰出資源,以便在要求工作3

我使用Javascript &的jQuery在客戶端。 PHP/Apache和SQL在服務器端。

+0

你試過緩存結果嗎?我個人建議安裝和使用memcached。添加一個類,你可以在1個月或1周後取決於你的需要 –

+0

也可以過期結果,看看下面的帖子http://stackoverflow.com/questions/13886501/ajax-abort-is-not-aborting -on-the-server-only-the-the-client –

+0

我同意你只是有一個架構問題的其他意見。被查詢數據的基數是多少(即緩存是否合理)。什麼是數據的大小?它是否適合特里結構或類似的搜索樹,使查找效率更高? –

回答

-1

我已經想出了一個很好的解決方案,我已經測試過,它的工作非常好。只需要幾行PHP代碼即可放入任何需要大量資源的文件。

該解決方案利用來自服務器的Process Identifier (PID)。我們可以使用兩個PHP函數:posix_getpid()獲取當前的PID和posix_kill()來殺死另一個PID。這也假設你已經在其他地方調用了session_start()。

下面的代碼:

//if any existing PIDs to kill, go through each 
if ($_SESSION['pid']) foreach ($_SESSION['pid'] as $i => $pid) { 

    //if posix_kill returns true, unset this PID from the session so we don't waste time killing it again 
    if(posix_kill($pid,0)) unset($_SESSION['pid'][$i]); 

} 

//now that all others are killed, we can store the current PID in the session 
$_SESSION['pid'][]=posix_getpid(); 

//close the session now, otherwise the PID we just added won't actually be saved to the session until the process ends. 
session_write_close(); 

幾件事情要注意:

posix_kill有兩個值。第一個是pid,第二個應該是來自this list的信號常量之一。沒有什麼對我有任何意義,其他人似乎只使用0就成功了,而當我使用0時,它返回true。所以無論工作!

在資源密集型事物開始發生之前調用session_write_close()至關重要。否則,保存到會話中的新PID將不會實際保存到會話中,直到完成所有頁面的處理。這意味着下一個過程將不知道取消還在繼續的過程。

+1

這似乎是一個非常糟糕的解決方案......您不應該惹惱服務器上的進程,必須有更好的解決方案。 –

+0

@FabienWarniez嗯,我已經有了這件事,而過去需要一分鐘才能完成的事情已經過去了3秒。殺死這樣的進程有什麼問題?我會崩潰服務器嗎?我會打開一個安全漏洞嗎? – rgbflawed

+1

不同的事情:1.根據腳本在殺死它時的行爲,查殺進程可以使DB或文件系統處於隨機狀態。 2.可維護性3.根據您承載代碼的位置,您可能並不總是有權這樣做。 4.有一個原因,這是一個安全漏洞,你給你的代碼太多的權限/權限,它最好是非常強大和防彈。 –

0
  1. 將數據庫中的布爾值存儲在表中或會話中。
  2. 讓您的資源密集型腳本定期檢查該值是否應該繼續。如果數據庫表示停止,那麼腳本會自行取消(例如,通過在當前函數中調用return;)。
  3. 當您想要取消而不是調用abort();時,請發出AJAX請求將該值設置爲false
  4. 下一次資源檢查該值時,它將看到它必須停止。

潛在限制: 1.您的腳本沒有定期檢查數據庫的方法。 2.根據腳本檢查數據庫的頻率,可能需要幾秒鐘纔能有效地終止腳本。

+0

這也是一個有趣的做法。我擔心必須對SQL進行大量的額外調用才能檢查是否應該繼續。我也關心這個「定期檢查」部分。定義週期性意義是非常困難的。當然,在這個資源密集的腳本中有很多循環正在進行,但是一個循環所花費的時間長度將完全不同,具體取決於所輸入的輸入以及從SQL中退出的結果。 – rgbflawed

+1

這就是爲什麼我建議會議。它可以是memcache,它可以是存儲這個布爾值的任何方式,以便簡單的AJAX調用可以讀/寫它。 –

+0

嗨@FabienWarniez,我剛來到這個線程尋找解決我的問題。我想停止瀏覽器「取消」的請求。當用戶在第一個請求回答之前切換到另一個網頁時會發生這種情況。當您在Chrome中按F12時,您可以以取消狀態顯示紅色請求。這可以發生在每個請求的所有時間,我不想管理數據庫存儲並檢查每個請求...(儘管很少是長btw,也許是20)。沒有更好的伎倆嗎?瀏覽器無法發送信號給服務器以取消已取消的請求(這是唯一知道它的地方)? –