socket.ioのxhr-pollingがボトルネックになっていたのはhttp-proxyの設定が関連していた!!!

こちらの続き。

そもそもなぜxhr-pollingのベンチをとりたくなったのか

スマートフォン向けのアプリだったのですが、実際にリリースしてみた結果
socket.ioのtransportでxhr-pollingが予想より多く発生していて、
さらにxhr-pollingによるレスポンス遅延がみられ、*1
さらにxhr-pollingが予想していたよりもだいぶボトルネックになってしまっていた
という事象が発生しており、そのためにベンチマーク取っておきたいなーと考えたわけです。

ベンチマークしてみた(数値なし)

現在の構成ではソケットサーバのフロントにnode-http-proxyを立てて、その裏にsocket.ioサーバが潜んでいます。

まずは、プロキシ経由で普通にベンチかけてみる

やはり思ったより性能出ない。。
というかCPU利用率があんまりあがらないのでどこかで別の原因で詰まっている?

次に、プロキシ通さずsocket.ioサーバに直接ベンチかけてみる

すると、おおよそ想定していたくらいの性能が出てる…!
ということはnode-http-proxyの問題か?

node-http-proxy README

よくよく見たらSocketLimitsに関する記述が…

Configuring your Socket limits
By default, node-http-proxy will set a 100 socket limit for all host:port proxy targets.
You can change this in two ways:

1. By passing the maxSockets option to httpProxy.createServer()
2. By calling httpProxy.setMaxSockets(n), where n is the number of sockets you with to use.

https://github.com/nodejitsu/node-http-proxy

デフォルト100までって書いてるし。。

maxSockets設定してみる

//※抜粋
var proxy = new httpProxy.HttpProxy({
  target: {
    host: 'localhost',
    port: 3001,
    maxSockets: 1000
  }
});

これ設定したら詰まることはなくなったっぽいYO!
\(^o^)/わーい

いろいろ反省点

  • スマートフォン向けということもあり、Websocketがほとんど占めるはずと考えて Websocketバージョンのベンチマークしかしていなかった。しかし実際にはWebsocket率が思ったより少なかった(おおよそ6割
  • よしんば他のtransportにフォールバックしてもそこまで性能が落ちないだろうと考えていた。(Web上に転がってるベンチマークの数値は確認した上での考察
  • Websocketでは発生せず、xhr-pollingでのみ発生するボトルネック。しかもプロキシを通した時だけに発生。これを見逃していた。


自分で推測した結果あてが外れて、
実際の本番構成で動かしてみなかったのは自分のミスでしたね。
というわけで自戒も含め、エンジニアには有名(?)なあの言葉で締めたいと思います。


推測するな、計測せよ

*1:この時はスケールアウトで難を逃れた