@hakoberaさん

@uchida75cmです。とても丁寧な解答ありがとうございます!
非常に助かりました。xhr-pollingがうまく動かないのはバグだったのですね。

socket.io-clientのバージョンをv0.9.2に、io.connect前にtransport書き換え
の2点を実施することで、xhr-pollingでの接続ができました。

元々の目的であった、負荷テストもこの方法で進めてみます。
ありがとうございました。



2012年8月28日火曜日 3時08分19秒 UTC+9 hakobera:
>
> 本多@hakobera です。 
>
> 以前に xhr-polling で動かした記憶があったのでおかしいなと思い、 
> 調べてみたら、これ、socket.io-client のバグですね。 
>
> 2つのバグが混ざっています。(2つ目は仕様かもしれませんが) 
>
> 1つ目は node 上での XHR の check メソッド内のバグ。 
>
> 具体的には、v0.9.3 で以下のコミットが入ったためです。 
>
>
> https://github.com/LearnBoost/socket.io-client/commit/b8c3f799363075d6ea9c2065cac59a58d660d7e4
>  
>
> 0.9.10 だと少し変数名が変わっていますが、以下の行です。 
>
>
> https://github.com/LearnBoost/socket.io-client/blob/master/lib/transports/xhr.js#L193
>  
>
> node 環境だと global.location が undefined であるために例外が発生し、 
> XHR.check() が常に false を返すため、Socket の生成に失敗し、コネクションが張れない(socket.js 
> の225行目で connect_failed イベントが発生する)ので、最終的に timeout してしまうのです。 
>
>
> https://github.com/LearnBoost/socket.io-client/blob/master/lib/socket.js#L225 
>
> これに関しては既に pull-request も上がっていますね。全然取り込まれないですけど。 
>
> https://github.com/LearnBoost/socket.io-client/pull/420 
>
> なので、現時点での対応策としては、 
>
> 1. 負荷テスト側では socket.io-client の 0.9.2 を使う 
> 2. socket.io-client を fork して修正したものを使う(修正方法は上記 pull request を参照) 
> 3. socket.io-client が修正されるのを待つ 
>
> のいずれかになると思います。 
>
> 2つ目のバグ(仕様?)は、 
> io.connect の option で transports を1つしか指定しなくても、 
> io.transports の設定が混ざりこんでしまうという問題です。 
>
> transport 固定しているのに以下の動きがおかしいなと思ったのです。 
>
> > xhr-polling指定   -->  指定なし              (websocketに切り替わって動作) 
>
> でも、実際にやってみたら、確かに websocket に切り替わるので、調べてみると、 
> Socket.transports のデフォルト値に io.transports が指定されており、 
> これが [ 'xhr-polling', 'websocket' ] という値であるためでした。 
>
>
> https://github.com/LearnBoost/socket.io-client/blob/master/lib/socket.js#L23-42
>  
>
> 指定された option.transports も merge しているのですが、 
> io.util.merge の実装で配列の merge は要素の追加なので、websocket という値が残ってしまい、server 側が 
> websocket 優先の設定になっていると、そちらで繋がってしまう、という状況でした。 
>
> これも socket.js の実装が以下のようになっていれば良いと思うんですが 
>
> this.options = { 
> ... 
>  , transports: options.transports ? [] : io.transports 
> ... 
> } 
>
> なっていないので、以下のように io.connect() を呼び出す直前で、 
> io.transports を書き換えることで一応回避できます。 
>
> var io = require('socket.io-client'); 
>
> io.transports = ['xhr-polling']; 
> var socket_xhr = io.connect(uri, { 
>   'try multiple transports': false, 
>   'force new connection': true 
> }); 
>
> io.transports = ['websocket']; 
> var socket_ws = io.connect(uri, { 
>   'try multiple transports': false, 
>   'force new connection': true 
> }); 
>
> もしくは server 側の transports の優先順位を xhr-polling -> websocket の順番にするかですね。 
>
> 2012年8月28日 2:14 atsuya <[email protected] <javascript:>>: 
> > こんにちは、高木です。 
> > 
> > "force new connection"オプションは指定されましたか? 
> > 
> > - 高木 
> > 
> > 
> > 2012/8/27 uchida75cm <[email protected] <javascript:>>: 
> >> @hakoberaさん 
> >> やりたい負荷テストは、おしえて頂いた方法で実現できそうです! 
> >> ありがとうございます。 
> >> 
> >> socket.io-clients側のtransportのoptionを指定してみたのですが、 
> >> うまくxhr-pollingで接続できず、タイムアウトになってしまう状況です。 
> >> 
> >> 環境は下記のような環境です。 
> >> OS: CentOS release 5.7 (Final) 
> >> Node: v0.6.19 
> >> Socket.IO: v0.9.10 
> >> Socket.IO-Client: v0.9.10 
> >> 
> >> いくつか試したパターンは下記のような結果でした。 
> >> client                  -->   server 
> >> 指定なし            -->  指定なし              (websocketで問題なく動作) 
> >> 指定なし            -->   xhr-polling指定    (タイムアウト) 
> >> xhr-polling指定   -->  指定なし              (websocketに切り替わって動作) 
> >> xhr-polling指定   -->  xhr-polling指定     (タイムアウト) 
> >> 
> >> ※ 動作したと判断している場合は、「任意に指定しているイベントのやりとりができた」 
> >> という状態です。 
> >> ※ タイムアウトになる場合も、server側のログでは、authorizationを通り、 
> >> socket.idが発行されているようでした。 
> >> 
> >> nodeやmoduleのバージョンでうまく動いていないかもしれないので、 
> >> バージョンなどを変えてもう少し触ってみます。ソースなども少し追ってみます。 
> >> 
> >> 何か進展があればまたこちらに書きたいと思います。 
> >> また相談させて頂くかもしれませんが、よろしくお願いします。 
> >> 
> >> 
> >> 
> >> 
> >> 
> >> 
> >> 
> >> 2012年8月27日月曜日 16時48分03秒 UTC+9 hakobera: 
> >>> 
> >>> 本多@hakobera です。 
> >>> 
> >>> 複数の transport が混在した環境をテストしたいというのであれば、 
> >>> transport 層を固定したクライアントを option 指定で別々に作れば良いのではないでしょうか。 
> >>> 
> >>> var uri = 'http://domain.com'; 
> >>> 
> >>> // for WebSocket 
> >>> var socket_ws =  io.connect(uri, { 
> >>>   transports: [ 'websocket' ], 
> >>>   'force new connection': true 
> >>> }); 
> >>> 
> >>> // for XHR-Polling 
> >>> var socket_xhr =  io.connect(uri, { 
> >>>   transports: [ 'xhr-polling' ], 
> >>>   'force new connection': true 
> >>> }); 
> >>> 
> >>> 各オプションの詳細は以下を参照してください。 
> >>> https://github.com/LearnBoost/socket.io-client#options 
> >>> 
> >>> force new connection はマニュアルに書いてないですが、 
> >>> これ書かないと、同じURLの場合にコネクションが使いまわされてしまい、 
> >>> 何個ソケット作っても実質1クライアントで負荷テストになりまし、 
> >>> 2つめ以降の options の設定が効きません。 
> >>> 
> >>> 
> >>> 
> https://github.com/LearnBoost/socket.io-client/blob/master/lib/io.js#L192-200 
> >>> 
> >>> 2012年8月27日 16:21 uchida75cm <[email protected]>: 
> >>> > こんにちは、uchida75cmといいます。 
> >>> > 
> >>> > Socket.IOサーバを使ったサービスの負荷テストをしたいと考えています。 
> >>> > transportsがwebsocketだけの場合には、socket.io-clientsなどで、 
> >>> > 複数接続を行い、検証することができるかと思うのですが。 
> >>> > 
> >>> > IEなど、xhr-pollingを利用するブラウザが混ざってくるような場合の環境を 
> >>> > シミュレーションして、負荷テストする方法はないでしょうか。 
> >>> > 
> >>> > 何か良い方法があればご教授いただけると幸いです。 
> >>> > よろしくお願いします。 
> >>> > 
> >>> > -- 
> >>> > 
> >>> > 
> >>> > 
> >> 
> >> -- 
> >> 
> >> 
> >> 
> > 
> > -- 
> > 
> > 
> > 
>

-- 



メールによる返信