nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

Nettyでab書いてみた

JBoss Advent Calendar 2011の27日目のエントリです。Nettyは非同期ネットワークアプリケーションフレームワークです。現在、NettyはJBossプロジェクトから移動中であり、JBoss NettyではなくNettyプロジェクトとして http://netty.io/ というサイトで独立することになります。

さて、Nettyを使ってなんか書いてみよう、と思ってとりあえずabを書いてみました。本家abは結果報告が詳細ですが、自分で書いたものは平均レスポンスタイム、成功と失敗リクエスト数くらいしか出ないものです。コードは以下に置いてありますが、ザラっと書いたものなのでかなり荒いです。

https://github.com/nekop/java-examples/tree/master/jab

Nettyのプログラミングモデルですが、基本的にはSimpleChannelHandlerを実装したら終わりです。channelConnected()やmessageReceived()といったイベントに対応したメソッドがあるのでそこに処理を書けば良いです。かんたん。

http://netty.io/docs/stable/api/org/jboss/netty/channel/SimpleChannelHandler.html

サーバはプロセス数100にしたnginxで、ベンチマーク対象データはddで100kbのファイルを作りました。

$ dd if=/dev/zero bs=1024 count=100 of=100kb.dat

同時接続数800、リクエスト数10000で計測しています。

結果

実装 平均レスポンスタイム
ab 130
HttpURLConnection 82
Netty Old IO 180
Netty New IO 190

結果の平均レスポンスタイムをそのままパフォーマンスの指標として解釈しないほうが良いです。

  • シンプルなユースケースはシンプルに書いたほうが速度が速くなるのは当然
  • 回数走らせるとかなり結果にブレがある
  • このベンチマーク作者はNettyのエキスパートではない
  • abはいろいろ集計してる

などなどの理由で、この結果はNetty遅い、とかそういう類のデータを示すものではありません。

HttpURLConnection実装

ExecutorとHttpURLConnectionでストレートに実装して、終了条件はリクエスト数のCountDownLatchを使っています。1分くらいで書けますね。

https://github.com/nekop/java-examples/blob/master/jab/src/main/java/jp/programmers/jab/StandardJAB.java

Netty実装

Netty実装は今の時点ではあまりきれいとは言えない出来です。問題はNIOで、HttpURLConnection実装のように「スレッド数 == 同時接続数」とはならないので、1リクエスト終了時に次のリクエストが飛ぶように、などの工夫が多少必要になってきます。しかし、状態はChannel毎に作成されるChannelHandlerのインスタンスフィールドなどに保持できてカプセル化できますし、イベントメソッドが分かれていて見通しも良いので、後から変更するのはそれほど面倒ではないです。

https://github.com/nekop/java-examples/blob/master/jab/src/main/java/jp/programmers/jab/NettyJAB.java

Old IOとNew IOがcreateChannelFactory()メソッドだけで切り替えられるように出来た、というのは素晴らしいところ。

Netty NIO

同時接続数800ですが、NIOを利用しているので800スレッドを使う必要はありません。今回は20スレッドで走らせた結果です。HttpURLConnectionとNetty Old IOでは800スレッドのExecutorが必要です。NIOはエコで地球にやさしい。

あと、同時接続数とかリクエスト数をあげていくと、channelOpen()とchannelClosed()だけ呼ばれる不思議なChannelが発生します。channelConnected()かexceptionCaught()のどちらかが呼ばれそうなものですが、そうならないパターンがあるようです。後で調べます。

どうでもいいこと

なぜかabの-cに700以上指定するとContent-Lengthを193バイトと誤認識して全部Lengthエラーだと報告される。なんだろう。