![見出し画像](https://assets.st-note.com/production/uploads/images/114690141/rectangle_large_type_2_bb98c7b5b438ba9969e4c7ebc74d0cf4.jpeg?width=1200)
Spring WebFluxでブロッキング処理を呼ぶ場合に気を付ける事
あいさつに代えて
今回の画像は、7月22日に羽田空港近くの「HANEDA INNOVATION CITY」へ行った際に撮影した空です。飛行機が写るまで頑張ろう、と思ったのですが猛暑で断念しました。
Spring WebFluxとは
Spring WebFluxとは、Spring Frameworkの一部で非同期・非ブロッキングのWebスタックフレームワークです。
サーブレットベースのSpring WebMVCと同様に、アノテーションベースで記載する事ができますが、少数のスレッドを有効利用する為、少ないハードウェアリソースで動作できるのが特徴です。
弊社提供のサービスでも、内部で一部利用されています。
今回はサービス開発時に発生した問題と、その解決策について書きたいと思います。
ブロッキング処理を呼ぶ場合の問題
Spring WebFluxでは、Reactive Streamsの実装としてReactorを利用しています。
通常ReactorのMonoやFluxを操作するラムダ式内では、スレッドを長時間保持するブロッキング処理を書かない様にするのですが、外部ライブラリを呼び出す等、どうしてもブロッキング処理を実行しなければならない場合があります。
何が問題か
次のコードで説明します。
Mono.fromCallable()内で指定したラムダ式は、実行時にReactorのスケジューラーを介して適用されたスレッドで実行されます。
Reactorのスケジューラーは、特に指定しない限りメソッドを呼び出した際のスケジューラーが利用されます。
このままでは、適用されたスレッドをこのブロッキング処理で占有していまいますので、他の処理が実行されない等の問題を引き起こします。
問題の解決策1 - スケジューラーにSchedulers.boundedElastic()を指定
Reactorでブロッキング処理を実行する為の方法として、スケジューラーにSchedulers.boundedElastic()を指定せよ、とリファレンスに記載があります。
これを前のコードに適用すると、次の様になります。
これで、大抵の場合は解決します。
但し大量のブロッキング処理を実行する際は、Schedulers.boundedElastic()スケジューラーを利用するSpring WebFluxや関連する他の部分の処理に影響を与える場合があります。
問題の解決策2 - スケジューラーに独自のboundedElasticスケジューラーを指定
ReactorのSchedulersクラスには、boundedElasticスケジューラーを作成するメソッドが用意されていますので、独自作成したスケジューラーを指定します。
これを前のコードに適用すると、次の様になります。
終わりに
Spring WebFluxはサーブレットベースとは異なり、少々難しい面もありますが利点もありますので、有効に利用してみましょう。