別のNIOのつまずき
Windows で動作し、Red Hat では動作しない小さなサーバーを使用しています。アイデアは次のとおりです。
- ServerSocketChannel と Selector を持つメイン スレッド
- 接続を受け入れると、SocketChannel を含む Event を作成します。
- イベントがキューに提供されます
- 各ワーカー スレッドには独自のセレクタと DB 接続があります。
- ワーカー スレッドはキューからイベントを取得し、そこにセレクタと DB 接続を設定し、イベントのメソッド getProcessed を呼び出します。
- Event は SocketChannel を読み取り (常に問題ありません)、DB で何かを実行し (常に問題ありません)、SocketChannel に書き込みます (Windows では機能し、Red Hat では機能しません)。
コードは次のとおりです。
public void processWriting()
throws Exception {
sk = client.register(selector, SelectionKey.OP_WRITE);
String s = "HTTP/1.1 301 Moved Permanently\r\n" +
"Location: " + resolution + "\r\n";
writeBuffer = ByteBuffer.wrap(s.getBytes("US-ASCII"));
LOGGER.trace("1. limit::" + writeBuffer.limit());
LOGGER.trace("1. position::" + writeBuffer.position());
LOGGER.trace("1. remaining::" + writeBuffer.remaining());
for (;;) {
selector.select(500);
// write once
for (Iterator<SelectionKey> it = selector.selectedKeys().iterator();
it.hasNext();) {
SelectionKey key = it.next();
it.remove();
if (key.isValid() && key.isWritable()) {
// write
client.write(writeBuffer);
}
}
// check all written out
if (!writeBuffer.hasRemaining()) {
break;
}
// check time
if (params.getTimeout() < processingTime()) {
break;
}
}
LOGGER.trace("2. limit::" + writeBuffer.limit());
LOGGER.trace("2. position::" + writeBuffer.position());
LOGGER.trace("2. remaining::" + writeBuffer.remaining());
if (writeBuffer.hasRemaining()) {
throw new Exception("writing failed");
}
writeBuffer = null;
}
ログ出力は次のとおりです。
2012-12-20 18:06:13,113 [TRACE] Thread-4:: bg.nalis.pidresolver.Event:: 1. limit::137
2012-12-20 18:06:13,113 [TRACE] Thread-4:: bg.nalis.pidresolver.Event:: 1. position::0
2012-12-20 18:06:13,113 [TRACE] Thread-4:: bg.nalis.pidresolver.Event:: 1. remaining::137
2012-12-20 18:06:13,113 [TRACE] Thread-4:: bg.nalis.pidresolver.Event:: 2. limit::137
2012-12-20 18:06:13,113 [TRACE] Thread-4:: bg.nalis.pidresolver.Event:: 2. position::137
2012-12-20 18:06:13,113 [TRACE] Thread-4:: bg.nalis.pidresolver.Event:: 2. remaining::0
コメントや提案をお待ちしております。