@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を利用するブラウザが混ざってくるような場合の環境を > >>> > シミュレーションして、負荷テストする方法はないでしょうか。 > >>> > > >>> > 何か良い方法があればご教授いただけると幸いです。 > >>> > よろしくお願いします。 > >>> > > >>> > -- > >>> > > >>> > > >>> > > >> > >> -- > >> > >> > >> > > > > -- > > > > > > > --
