簡體   English   中英

在Internet Explorer中,使用POST請求的AJAX應用程序總是會失敗嗎?

[英]Do AJAX applications that use POST requests always fail in Internet Explorer?

我最近發現,使用Internet Explorer運行我的應用程序的用戶間歇性故障的問題是由於Internet Explorer中的錯誤。 該錯誤位於HTTP堆棧中,應該使用來自IE的POST請求影響所有應用程序。 結果是失敗的特征是請求似乎掛起約5分鍾(取決於服務器類型和配置),然后從服務器端失敗。 服務器放棄后,瀏覽器應用程序將在post請求中出錯。 我將在下面詳細解釋IE錯誤。

據我所知,如果請求是在錯誤的時刻發送的,那么使用XMLHttpRequest將POST請求發送到服務器的任何應用程序都會發生這種情況。 我編寫了一個示例程序,試圖在這些時間發送POSTS。 它會嘗試在服務器關閉連接的精確時刻向服務器發送連續的POST。 間隔源自服務器發送的Keep-Alive標頭。

我發現當從IE運行到具有一點延遲的服務器(即不在同一個LAN上)時,問題只發生在幾個POST之后。 當它發生時,IE鎖定得如此之難以至於必須強制關閉。 滴答時鍾表示瀏覽器仍在響應。

您可以通過瀏覽到http://pubdev.hitech.com/test.post.php來嘗試。 請注意,在運行任何IE會話時,您沒有任何重要的未保存信息,因為我發現它會導致IE崩潰。

完整的源代碼可以在以下網址獲取: http//pubdev.hitech.com/test.post.php.txt 您可以在任何具有php並配置為持久連接的服務器上運行它。

我的問題是:

  1. 其他人對此問題的體驗是什么?

  2. 是否有解決此問題的已知策略(“使用其他瀏覽器”除外)?

  3. 微軟是否比我找到的文章(見下文)有更好的信息?

問題是Web瀏覽器和服務器默認使用持久連接,如RFC 2616第8.1節(參見http://www.ietf.org/rfc/rfc2616.txt )中所述。 這對性能非常重要 - 特別是對於AJAX應用程序 - 並且不應禁用。 然而,在服務器決定連接空閑並決定關閉它的同時,瀏覽器可能開始在先前使用的連接上發送POST的小定時孔。 結果是瀏覽器的HTTP堆棧將出現套接字錯誤,因為它使用的是封閉套接字。 RFC 2616第8.1.4節預見到了這種情況,並指出“......客戶端,服務器和代理必須能夠從異步關閉事件中恢復。客戶端軟件應該重新打開傳輸連接並重新傳輸請求的中止序列,而無需用戶交互......”

發生這種情況時,Internet Explorer 重新發送POST,但是當它發生時,它會破壞請求。 它發送POST標頭,包括發布的數據的Content-Length,但它不發送數據。 這是一個不正確的請求,服務器將在請求失敗之前等待承諾數據的未指定時間。 我已經能夠使用模擬HTTP服務器的C程序100%地演示此失敗,該服務器關閉傳入POST請求的套接字而不發送響應。

Microsoft似乎在http://support.microsoft.com/kb/895954中承認此失敗。 他們說它影響了IE版本6到9.這提供了一個針對此問題的修補程序,自IE 7以來已經附帶了IE的所有版本。由於以下原因,此修補程序似乎不滿意:

  1. 除非您使用regedit將名為FEATURE_SKIP_POST_RETRY_ON_INTERNETWRITEFILE_KB895954的密鑰添加到注冊表,否則不會啟用它。 這不是我希望用戶必須做的事情。

  2. 此修補程序實際上不會修復損壞的POST。 相反,如果套接字按照RFC的預期關閉,它只會立即出錯,而不會嘗試重新發送POST。 應用程序仍然失敗 - 它只是更快失敗。

以下示例是一個自包含的php程序,用於演示該錯誤。 它會嘗試在服務器關閉連接的精確時刻向服務器發送連續的POST。 間隔源自服務器發送的Keep-Alive標頭。

我們經常在IE上遇到這個問題。 沒有好的解決方案。 保證解決問題的唯一解決方案是確保Web服務器keepalive超時高於瀏覽器keepalive超時(默認情況下,IE為60s)。 Web服務器設置為較低值的任何情況都可能導致IE嘗試重用連接並發送由TCP RST拒絕的請求,因為套接字已關閉。 如果Web服務器keepalive超時值高於IE的keepalive超時,那么IE重用連接可確保套接字不會被關閉。 對於高延遲連接,您必須考慮延遲時間,因為在傳輸過程中花費的時間可能是一個問題。

但請記住,增加服務器上的keepalive意味着空閑連接使用服務器套接字的時間要長得多。 因此,您可能需要調整服務器的大小以處理大量不活動的空閑連接。 這可能是一個問題,因為它可能導致服務器無法處理的服務器負載突發。

要記住的另一件事。 您注意到RFC 8.1.4規定:“...客戶端,服務器和代理必須能夠從異步關閉事件中恢復。客戶端軟件應該重新打開傳輸連接並重新傳輸請求的中止序列,而無需用戶交互。 “。

你忘記了一個非常重要的部分。 以下是全文:客戶端軟件應該重新打開傳輸連接,並在沒有用戶交互的情況下重新發送中止的請求序列,只要請求序列是冪等的(參見第9.1.2節)。 非冪等方法或序列不得自動重試,盡管用戶代理可以為人類操作員提供重試請求的選擇。 具有對應用程序的語義理解的用戶代理軟件的確認可以替代用戶確認。 如果第二個請求序列失敗,則不應重復自動重試

HTTP POST是非冪等的,如9.1.​​2所定義。 因此,根據RFC,注冊表黑客的行為實際上在技術上是正確的。

不,通常POST在IE中工作。 這可能是一個問題,你在說什么,但這不是一個重要的問題,值得這篇巨大的帖子。

當您發出POST ajax請求時,為了確保涵蓋每個瀏覽器的不一致,只需使用jquery即可。

還有一件事:沒有人理智會告訴你“使用另一個瀏覽器”,因為IE被廣泛使用並且需要照顧(好吧,除了IE6以及某些,甚至一些較新的版本)

因此,POST 必須在IE中工作,但是為了讓自己適應意外的錯誤行為,使用jquery並且你可以睡得好。

我從未遇到過這個問題。 我們的客戶大多運行IE6。

我懷疑你已經將保持活動計時器配置得太久了。 大多數人將其配置為低於1秒,因為持久連接僅用於加速頁面加載而不是服務Ajax調用。

如果你將keep-alive配置得太長,你將面臨比IE崩潰更嚴重的問題 - 你的服務器會耗盡文件描述符來打開套接字!*

*注意: 順便說一句,打開和不關閉到HTTP服務器的連接是眾所周知的DOS攻擊,它試圖強制服務器達到其最大開放套接字限制。 這就是為什么大多數服務器管理員還配置連接超時以避免套接字打開太長時間的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM