Client(Browser) <----> Web/App(Netty) <----> DataStore(MongoDB/PostgreSQL etc)
前提条件: NettyのEventLoop数は1とする。
DataStoreへ接続するWebアプリケーション(以下Nettyアプリ)のNonBlockingの動作予想。
- ClientがNettyアプリに接続(HTTPリクエスト)
- NettyアプリからDataStoreに接続&データ取得処理(例えば
SELECT * FROM hoge
) - ただしNonBlockingなので2番の処理が終わるのを待つこと無く速攻returnされる
- Nettyアプリ側ではSelector(epoll)を使って、上記の状態を監視
- Clientからアクセスが来る度に1から4が繰り返される。
- Nettyアプリ側でSelector(epoll)が反応、つまりDataStoreから結果が返って来た。
- その結果をClientにreturn(HTTPレスポンス)
疑問:
実際のところ、2番の処理(SQLとか)自体はEventLoopではない別のスレッドが生成orプールから取得されて利用されているのでは?
MongoDBのNonBlocking用のドライバを試してみても、org.reactivestreams.Subscriber#onNext
はmainとは違うスレッドを生成して実行されている。
実際に以下のような感じになった。
上記のMongoDBのNonBlocking用のドライバを使って実際にサンプルコードを書いてみた。
これは単純に単体のスクリプトとして実行しているのでNettyとかはひとまず関係なし。
以下のようなSubscriberを用意。(抜粋。サンプルコードにスレッド名表示のprintを追加しただけ)
@Override
public void onSubscribe(final Subscription s) {
println "${Thread.currentThread().name} in Subscriber#onSubscribe"
subscription = s
}
@Override
public void onNext(final T t) {
println "${Thread.currentThread().name} in Subscriber#onNext"
received.add(t);
}
@Override
public void onComplete() {
println "${Thread.currentThread().name} in Subscriber#onComplete"
completed = true;
latch.countDown();
}
以下のようなコードでMongoDBを利用
MongoClient mongoClient = MongoClients.create("mongodb://127.0.0.1:27017")
MongoDatabase database = mongoClient.getDatabase("mydb")
MongoCollection<Document> collection = database.getCollection("test")
println Thread.currentThread().name
println "A"
collection.find().first().subscribe(new PrintDocumentSubscriber());
println('B')
sleep(500) // 結果をコンソールに表示するため
実行結果は
main
A
main in Subscriber#onSubscribe
B
Thread-6 in Subscriber#onNext
{ココにMongoDBのfind結果が出力されるー}
Thread-6 in Subscriber#onComplete
このことから、確かにMongoDBからデータを取得する部分はNonBlockingで動作していることがわかる。
が、これは単純に別のスレッドで動いているだけで、Nettyアプリにアクセスされる度に上記のコードが実行されるのであれば、アクセス数分のMongoDB用のスレッドが作成されるのでは、という部分が疑問。
さらに、別スレッドで動いているということはSelector(epoll)の監視対象にはなっていないのでは?という疑問もある。