2011年6月27日月曜日

Red5のマルチスレッドが詰まる?対処その1

Red5というか、ApacheMinaのNioSocketAcceptorをつかったサーバーが、だいたい詰まるっぽい。

というわけで、問題点と対処方法その1(シリーズ化するかはまだわからないけど)
例としてxmlsocketサーバーのプログラムをあげてみます。

このプログラムはRed5のorg.red5.server.net.rtmpのTransportの部分を参考にして、書いてみました。
こちらのjavaファイルをみてもらえればわかりますが、Executorを2つ準備して、コネクト用とIO処理用にスレッドのpoolを割り当ててます。

Executor connectionExecutor = Executors.newFixedThreadPool(connectionThreads);
Executor ioExecutor = Executors.newFixedThreadPool(ioThreads);
acceptor = new NioSocketAcceptor(connectionExecutor, new NioProcessor(ioExecutor));
この状態で、IoHandler側にどのスレッドで動作しているか確認するために
そうですね・・・messageReceivedあたりにThread.currentThread().toString()でもいれて動作スレッド情報をぬきとると、だいたいすべて同じThreadをつかって動作しているようになります。
というわけでうまくマルチスレッド化していません。

どうやら、ApacheMinaのライブラリの内部でプロセスをわりあてる部分がうまく動作していないようです。
ではどうすればいいかというと、

acceptor = new NioSocketAcceptor(Runtime.getRuntime().availableProcessors());
このように、存在プロセス数をわたしてやると、接続した順に処理スレッドが割り当てられるようになります。
たとえばCPUが4つのサーバーなら・・・
1→2→3→4→1と順繰りに使われるようになります。
一応apacheMinaのソースコードをひもといてみると、どうやら数字をいれてやるとapache.minaのライブラリにある、SimpleIoProcessorPoolというものが内部で自動生成されているようです。
acceptor = new NioSocketAcceptor(new SimpleIoProcessorPool<NioSession>(NioProcessor.class, 4));
自分で書くとこんな感じになるらしい。(自分で書くのはおすすめしません、なぜならpoolを自分で破棄しないとだめだからです。数字をわたすだけなら、NioSocketAcceptorが自分で管理してくれます。)
Executorsから引き出せるデフォルトのスレッドプールじゃないところがにくいですね。

これで一応、接続ごとに利用するスレッドはばらばらにできるわけですが、贅沢をいうなら接続ごとではなく、処理ごとにThreadがばらばらになれば、一番効率がいいはずなんで、その2をかくとすればそこの対処を書きたいところです。

なお、Red5のorg.red5.server.net.rtmp.RTMPMinaTransport.javaの中の書き方はExecutorを指定するようになっていますので、どうしてもRed5の動作がかく付くなんとかしたいという人は、NioSocketAcceptorの使い方の部分を書き換えちゃってコンパイルしちゃうのもありかもしれません。
え、いや、保証はしませんよ?

0 件のコメント:

コメントを投稿