Skip to content

Instantly share code, notes, and snippets.

@koji-k
Last active July 3, 2018 10:37
Show Gist options
  • Save koji-k/4cf2b218ab43a00b827cd7a0d9d6a5e1 to your computer and use it in GitHub Desktop.
Save koji-k/4cf2b218ab43a00b827cd7a0d9d6a5e1 to your computer and use it in GitHub Desktop.
NonBlockingなデータストアへのアクセスについて

Client(Browser) <----> Web/App(Netty) <----> DataStore(MongoDB/PostgreSQL etc)

前提条件: NettyのEventLoop数は1とする。

DataStoreへ接続するWebアプリケーション(以下Nettyアプリ)のNonBlockingの動作予想。

  1. ClientがNettyアプリに接続(HTTPリクエスト)
  2. NettyアプリからDataStoreに接続&データ取得処理(例えばSELECT * FROM hoge
  3. ただしNonBlockingなので2番の処理が終わるのを待つこと無く速攻returnされる
  4. Nettyアプリ側ではSelector(epoll)を使って、上記の状態を監視
  5. Clientからアクセスが来る度に1から4が繰り返される。
  6. Nettyアプリ側でSelector(epoll)が反応、つまりDataStoreから結果が返って来た。
  7. その結果を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)の監視対象にはなっていないのでは?という疑問もある。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment