web-dev-qa-db-ja.com

Spring Reactor Webfluxスケジューラーの並列処理

完全にノンブロッキングのエンドツーエンドのリアクティブコールの場合、publishOnまたはsubscribeOnを明示的に呼び出してスイッチスケジューラに切り替えることをお勧めしますか? CPUを消費するタスクと消費しないタスクのどちらでも、常に並列フラックスを使用してパフォーマンスを最適化することは好都合ですか?

3
user1955934

完全にノンブロッキングのエンドツーエンドのリアクティブコールの場合、publishOnまたはsubscribeOnを明示的に呼び出してスイッチスケジューラを呼び出すことをお勧めしますか?

publishOnは、データをダウンストリームに公開するときに使用され、subscribeOnは、アップストリームからデータを使用するときに使用されます。ですから、それはあなたがどのような仕事をしたいかによります。

CPUを消費するタスクと消費しないタスクのどちらでも、パフォーマンスを最適化するために常に並列フラックスを使用することは好都合ですか?

絶対にそうではありません、この例を考えてみましょう:

Flux.range(1, 10)
        .parallel(4)
        .runOn(Schedulers.parallel())
        .sequential()
        .elapsed()
        .subscribe(i -> System.out.printf(" %s ", i));

iはほぼ瞬時に処理されるため、上記のコードは無駄です。以下のコードは、上記よりもパフォーマンスが向上します。

Flux.range(1, 10)
        .elapsed()
        .subscribe(i -> System.out.printf(" %s ", i));

これを検討してください:

public static <T> T someMethodThatBlocks(T i, int ms) {
    try { Thread.sleep( ms ); }
    catch (InterruptedException e) {}
    return i;
}

// some method here
Flux.range(1, 10)
        .parallel(4)
        .runOn(Schedulers.parallel())
        .map(i -> someMethodThatBlocks(i, 200))
        .sequential()
        .elapsed()
        .subscribe(i -> System.out.printf(" %s ", i));

出力は次のようになります。

 [210,3]  [5,1]  [0,2]  [0,4]  [196,6]  [0,8]  [0,5]  [4,7]  [196,10]  [0,9] 

ご覧のとおり、最初の応答は210ミリ秒後に受信され、その後に0の経過時間の間に3つの応答が続きました。このサイクルは何度も繰り返されます。ここで、並列フラックスを使用する必要があります。より多くのスレッドを作成してもパフォーマンスが保証されるわけではないことに注意してください。スレッドの数が増えると、コンテキストの切り替えによってオーバーヘッドが大幅に増加するため、デプロイメント前にコードを十分にテストする必要があります。多くのブロッキング呼び出しがある場合、CPUあたりのスレッド数が1を超えるとパフォーマンスが向上する可能性がありますが、CPUを集中的に使用する場合は、CPUあたりのスレッドが複数あると、コンテキストの切り替えによりパフォーマンスが低下します。

つまり、全体として、それは常に何を達成したいかに依存します。

1
Aniket Sahrawat