著作一覧 |
XMLHttpRequestを使うページのテストをしている。
1つのページでイベント受信用と送信用で2つ使う。受信用で使うってことはつまり、Cometというわけだが。
問題は、Cometのパフォーマンスを見たくて、「新規ウィンドウ」を開くところから始まった。イベントは受信できるのに送信できない。タイミングによっては送信できるけど受信はできない。なにがなにやら。あるいは完全にハングしてプロセスを殺すしか手段がなくなったりもする。
で、いろいろ試行錯誤してるうちに、どうもインスタンスが同時に2つしか作れないんじゃないかと気づいた。
で検索すると Ajax-Development-Gotchasなんてページが見つかった。
IEは長年に渡る標準を無視する伝統を打破してRFC2616に従ったので2インスタンスしか同時に実行しないと書いている。しかもそれ以上の作成要求はキューする――これはハングしたように見えることと合致する。2つのページで同時に要求出すとデッドロックするからだ。ってことは、予測通りみたいだな。
これか! (8.1.4 Practical Considerations)
Clients that use persistent connections SHOULD limit the number ofsimultaneous connections that they maintain to a given server. A
single-user client SHOULD NOT maintain more than 2 connections with
any server or proxy. A proxy SHOULD use up to 2*N connections to
another server or proxy, where N is the number of simultaneously
active users. These guidelines are intended to improve HTTP response
times and avoid congestion.
まあ、標準に従うことは良いことだ。
ということから結論としては、Cometページは1ホストあたり最大2ページ。Ajaxを利用して送信もするなら1ページのみ(ロングポール用とAjax用)、それ以上のページを新規作成されると最悪デッドロックする。
注)FirefoxはConnetion: closeを送ってくる。Ajaxを多用すると細かなコネクションの生成/廃棄が山となる。IEは、Connection: Keep-Aliveだけど、サーバでちゃんと意識しないと細切れ返送だけに生成/廃棄がやはり山となる。
確か、RFCに上記の制限が必要となった理由のひとつにコネクション生成/廃棄(生成は処理的なオーバーヘッド――まあいろいろ理由はあるけど例えばある種の攻撃回避のための動作とか、廃棄の場合はCLOSE_WAITの期間の利用不可ソケットが問題となったはず)が問題となったのだと思う(ネスケがやみくもにimgを表示するためにサーバーに接続してきたあたり。確か4コネクション使ってたような記憶があるけど違うかも)が、AjaxはOKなのか? とちょっと疑問を持ったり。最近のサーバーは高速だからOKならば、上記のRFCの制限についてもちょっと緩めて欲しいなとも思ったり。
追記:『WinInetの設定を変える』。HTTP/1.0の場合は4か……
更に追記:試した。4にしたら2ページで動く。テスト時の緊急避難的設定だな(と2に戻すというか、エントリを削除するのが筋袋かも)
# change_httpcon.rake require 'win32ole' CONN_PER_SERVER = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\MaxConnectionsPerServer' WSH = WIN32OLE.new('WScript.Shell') task :set_more do WSH.RegWrite CONN_PER_SERVER, 8, 'REG_DWORD' puts WSH.RegRead(CONN_PER_SERVER) end task :reset do begin WSH.RegDelete CONN_PER_SERVER puts WSH.RegRead(CONN_PER_SERVER) rescue puts $!.message end end実行結果(レジストリ見なきゃ意味ないけど)
C:\home\test>rake -f change_httpcon.rake set_more (in C:/home/test) 8 C:\home\test>rake -f change_httpcon.rake reset (in C:/home/test) RegRead OLE error code:80070002 in WshShell.RegRead レジストリ キー "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\MaxConnectionsPerServer" を開いて読み取ることができません。 HRESULT error code:0x80020009 例外が発生しました。
ジェズイットを見習え |
一部の人は仕方なくひとつの接続上でプロトコルを決めて多重化してるらしいです:
- http://cometd.com/
- http://svn.xantus.org/shortbus/trunk/bayeux/protocol.txt
- http://svn.dojotoolkit.org/dojo/trunk/src/io/cometd.js
これはおもしろいですね。どうもありがとうございます。
もっと見てみたいけどajaxian.comというのが今は落ちてるみたいなのが残念。
(全然このへんをキャッチアップできてないんだなとしみじみ思った)
今見たらajaxian.comは動いてた。