
我有一個相當資源密集的 CGI,需要很長時間才能開始發送資料。我們見過很多這樣的情況:不耐煩的人會重新加載幾次,然後觸發要加載的 CGI 的額外運行,或者客戶端超時並斷開連接,但 CGI 繼續運行的情況。
有什麼好的方法可以偵測到這種情況何時發生嗎?它甚至不需要位於 CGI 本身內(如果不是的話可能會更好 - 它會交給我無法控制的另一個程序),但可能是一個經常運行的 cron 作業尋找死連接來收穫。
我目前正在使用 Apache,但這是一個問題,如果它有處理它的規定(或讓我監視問題的方法),我願意運行其他網路伺服器。
答案1
通常,在開始寫回使用者之前,您無法偵測到斷開的連線。否則,您的進程將繼續執行其工作,而不會注意到用戶端的連線中止。這個帖子即使談論 PHP 也是相關的。概念應該是一樣的。
您可以嘗試以下幾種方法:
- 在後台完成耗時的工作。當使用者請求 CGI 時,不要將任務作為正常的阻塞呼叫來執行。只需向用戶返回任何內容以告知該請求正在處理中即可。當然,您需要找到某種方法來更新檢視或提供另一個頁面來使用某些請求 ID 或 IP 檢查作業狀態。
- 盡快將資料傳回客戶端,如果發送失敗則退出(表示連線中斷)。例如,您可以每隔幾秒鐘或幾分鐘發送作業進度。
如果將目前正在執行的作業儲存在資料庫中,則可以儲存請求 ID 和/或用戶端 IP 位址。因此,您可以偵測並忽略對相同資源的重複請求,告訴使用者「您的請求正在處理中」。
答案2
警告:此資訊可能已過時。參見最後一段。
我記得曾經遇到過同樣的問題,並用一個解決方案神經網路PH(無解析標頭)CGI 腳本。
通常,apache 會從您的腳本中收集所有標頭,並在讀取完標頭後,使用您未提供的一些標準標頭來修改它們。這也意味著,只要您沒有完成標頭,apache 就不會向客戶端發送任何內容。
使用 nph 腳本,您必須提供所有標頭,但 apache 會立即將它們傳送到用戶端,並在用戶端斷開連線後向您的 CGI 腳本發送 SIGPIPE。因此,您可以X-Slowly-Counting-Part-nnn: yes
每隔幾秒鐘發送一些標頭,以防止客戶端逾時,並且如果客戶端中斷連接,您將收到通知。
這仍然留下一個問題,您必須先發送 HTTP 狀態,但如果您發送“內容長度:0”,或者可能是“內容長度:1”並關閉連接而不發送任何內容,您的檔案下載器應該假設出現網路錯誤並採取相應措施。
您可能必須透過您的進程傳輸其他程式的輸出,但是至少如果您在 Linux 上並使用系統sendfile(2)
調用,這不會對效能造成重大影響。
所有這一切的問題是我至少在 10 年前使用過它,可能是在 Apache 1.3 上,而谷歌搜尋apache cgi nph
沒有產生任何有用的東西。所以也許 nph 功能同時被刪除了 - 但也許不是,我承認我沒有仔細看。
答案3
舊問題,但我遇到了同樣的問題並解決了檢查連接是否已建立的問題:
就我而言,我在伺服器上執行 bash 腳本。
ss -nt state established "( sport = :$SERVER_PORT and dport = $REMOTE_ADDR:$REMOTE_PORT )" 2>/dev/null | grep -q "$REMOTE_ADDR:$REMOTE_PORT"
if [ "$?" -ne '0' ]; then
# Client closed browser/connection
fi