2011年11月16日水曜日

IEにおけるXMLHttpRequestの不具合

ExtJSを使っているとAjax通信を多用しますよね。

さて今日はIEでのAjax通信のお話。

とあるシステムでExtJS(バージョン3.3)のExt.Ajax.requestを使ってPOSTしている部分があるけど、なぜかたまーにコールバックに返ってこない場合がありました。しかもIEでばっかり起こる。パケットキャプチャしてみると、サーバー側にPOSTデータが送られてない。5分後にサーバー側でタイムアウトして、処理を中断してました。

  • IEはデータを送ったつもり
  • でもサーバーには届いていない
  • サーバーは5分間じっと待つけど、もう無理!って諦める
  • IEはサーバーからの返答をじっと待つ

サーバーとIEがすれ違いなんですね。気持ちが届かないって、はがゆいよね。

で、この現象、結論から言うと、IEのバグじゃないの?ってことです。英語ですが、こんな投稿をみつけました。

XMLHttpRequest POST sometimes fails when server is using keep-aliv


ざっくり翻訳しました。ところどころ意味が通りやすいように意訳してる箇所もありますが、意味不明なところがあれば原文を参照してください。。。


サーバーがkeep-aliveを設定している時、XMLHttpRequestのPOSTが時々失敗する


2004年、IE6において、サーバーがコネクションをリセットした場合、POSTリクエストのbodyが失われてしまうというバグがありました(http://support.microsoft.com/kb/831167/en-us)。同じバグがどうやら(少なくとも)IE6,7,8のXMLHttpRequestにも存在しているようです。

この問題は、keep-aliveタイムアウトに短い時間(たとえば10秒とか)を設定しているサーバーに対してXMLHttpRequestをPOSTすることによって簡単に再現できます。もし、POSTリクエストがkeep-aliveが切れる直前に作られていたとして、そこにわずかなネットワークの遅延があったとすれば、Webサーバーはコネクションをリセットして、IEにリクエストを再送することを強要します。この時、IEはContent-Lengthヘッダーは送り直すのですが、bodyを送信するのを"忘れ"ます。結果として、サーバーではタイムアウトが発生するまで、bodyが到着するのを待つことになります。

"keep-aliveの直前"と"わずかなネットワーク遅延"というと、このバグの再現が難しそうに思えますが、モダンなWebアプリを例えばモバイル回線などを使って利用しているとそう難しくありません。

この問題のデモをhttp://artur.virtuallypreinstalled.com/apache2-default/ie-xhr.phpに置いています(訳注:現在はリンク切れのようです)。keep-aliveタイムアウトを15秒に設定しているので、14~15秒待って、ボタンをクリックしてください。レスポンスがきちんと返ってきたらアラートがポップアップされ、ボタンが再度有効になるはずです。少なくとも私がモバイル回線を使ってやると、IE8で2~3回で問題が再現します。

サーバーのkeep-aliveをオフにするのが唯一の解決策だと思われます(もしくは、keep-aliveタイムアウトを60秒以上に設定することでも解決するかもしれません)。他に誰かこのようなことが起こっていませんか?他の解決策はありませんか?過去にこの問題について報告されたり議論されたりしていませんか?



ということらしいです。この投稿のレスで「私もその現象起こったよ!」って言ってる人もいます。実際、うちのサーバーのkeep-aliveは5秒になってました。ためしにkeep-aliveを切ったら(offにした)、システムのレスポンスが著しく低下してしまって、結局切り戻し。今はkeep-aliveの時間を伸ばして様子見。それでもまだ現象は発生してるけど、回数は少なくなったような・・・。

これが、本当にIEのバグならはやく直って欲しいが・・。

プログラムではどうしようもないような、こういう問題はやっかいだなぁ(・。・;

0 件のコメント:

コメントを投稿