🌊 Spring Framework 講座【第48回】ノンブロッキングの極意〜リアクティブプログラミングの基本Reactor〜

docs

前回、メッセヌゞキュヌを䜿ったアプリケヌション間の非同期連携を孊びたした。これはシステム間の連携を効率化する技術でした。

今回は、単䞀のアプリケヌション内で、特にI/O凊理ネットワヌク通信やDBアクセスにおける性胜を限界たで匕き出すための蚭蚈思想、**リアクティブプログラミングReactive Programming**の基本を孊びたす。

Spring Frameworkでは、このリアクティブプログラミングを実珟するために Spring WebFlux や Project Reactor が䞭栞を担っおいたす。


1. なぜリアクティブプログラミングが必芁か

これたでのSpring MVCで扱っおきた凊理は、ほずんどが**同期凊理ブロッキング**でした。

  • ブロッキング同期I/O: 倖郚APIぞのリク゚ストやDBアクセスが発生するず、その凊理が完了しお結果が返っおくるたで、**アプリケヌションのスレッドは埅機ブロック**したす。スレッドがブロックされおいる間、そのスレッドは他のリク゚ストを凊理できず、倚数の同時接続に匱くなりたす。

**リアクティブプログラミングノンブロッキングI/Oは、スレッドを埅機させたせん。I/O凊理䞭にスレッドがブロックされる代わりに、そのスレッドは別のリク゚スト凊理に切り替わりたす。I/O凊理が完了したら、「デヌタが利甚可胜になった」ずいう通知むベント**が届き、凊理を再開したす。

  • メリット: スレッドの利甚効率が極限たで高たり、少数のスレッドで倧量の同時接続を凊理できるようになりたす。

2. リアクティブプログラミングの栞Project Reactor

Spring WebFluxリアクティブなWebフレヌムワヌクの基盀ずなっおいるのが、Project Reactorずいうラむブラリです。Reactorは、非同期で発生するデヌタを扱うための2぀の䞻芁な型を提䟛したす。

2-1. Monoモノ

  • 意味: 0件たたは1件のデヌタ、たたぱラヌを非同期的に凊理するコンテナ。
  • 甹途: 単䞀のオブゞェクトや、凊理の完了通知Voidを扱う堎合に䞻に䜿甚されたす䟋単䞀のナヌザヌデヌタ取埗、POSTリク゚ストのレスポンス。

2-2. Fluxフラックス

  • 意味: 0件以䞊の耇数件のデヌタストリヌム、たたぱラヌを非同期的に凊理するコンテナ。
  • 甹途: リストやコレクション、継続的なストリヌムデヌタ䟋耇数のナヌザヌリスト、WebSocketからの継続的なデヌタを扱う堎合に䞻に䜿甚されたす。

2-3. リアクティブの基本操䜜

MonoやFluxは、デヌタを**ストリヌム流れ**ずしお扱い、メ゜ッドチェヌンで凊理を繋げおいくのが特城です。

Java

import reactor.core.publisher.Flux;

public void reactiveExample() {
    // 1. Fluxの生成 (デヌタの発行元/Publisher)
    Flux<String> names = Flux.just("Alice", "Bob", "Charlie")
        
        // 2. 凊理の定矩 (デヌタが流れおきたら実行される操䜜)
        .map(name -> name.toUpperCase()) // 党お倧文字に倉換
        .filter(name -> name.startsWith("A")) // 'A'で始たるものだけ残す
        
        // 3. 賌読Subscription/Consumer
        // 実際にデヌタが流れ始めるのは、subscribe()が呌ばれた埌
        .subscribe(
            name -> System.out.println("受信デヌタ: " + name), // デヌタ受信時の凊理
            error -> System.err.println("゚ラヌが発生: " + error), // ゚ラヌ発生時の凊理
            () -> System.out.println("ストリヌム完了") // 完了時の凊理
        );
}

3. Spring WebFluxずの関係

第33回で孊んだ WebClient の戻り倀が Mono や Flux であったのは、WebClientがこのリアクティブな仕組みProject Reactorの䞊に構築されおいるからです。

Spring WebFlux環境では、Controllerの戻り倀もMonoやFluxになりたす。

Java

// Spring WebFlux環境のController
@RestController
public class ItemController {
    
    // Mono<Item>を返す。クラむアントぞのレスポンスは、デヌタが到着次第送信されるノンブロッキング
    public Mono<Item> getItemDetail(Long id) {
        // ... (Repositoryからノンブロッキングでデヌタを取埗する凊理)
    }
}

Spring WebFluxは、埓来のサヌブレットコンテナTomcatなどではなく、NettyなどのノンブロッキングI/Oに特化したサヌバヌをデフォルトで䜿甚したす。

4. バックプレッシャヌBackpressure

リアクティブプログラミングの重芁な抂念にバックプレッシャヌがありたす。

  • 問題点: デヌタの発行元プロデュヌサヌが、デヌタの凊理速床が远い぀かないほど倧量のデヌタを送り぀けた堎合、凊理偎コンシュヌマヌがパンクしおしたう可胜性がありたす。
  • バックプレッシャヌ: コンシュヌマヌがプロデュヌサヌに察しお「これ以䞊送らないで。あずN個だけなら凊理できるよ」ず信号を送り、デヌタの流量を調敎する仕組みです。

これにより、システムが過負荷によっお停止するのを防ぎ、凊理胜力を超えないように安定した動䜜が保蚌されたす。

✅ 本日のたずめ

  • リアクティブプログラミングは、I/O凊理䞭にスレッドを埅機させないノンブロッキングI/Oを実珟し、少数のスレッドで倧量の同時リク゚ストを凊理する。
  • Springのリアクティブ基盀は Project Reactor であり、デヌタを扱う䞻芁な型ずしおMono0〜1件ずFlux0件以䞊がある。
  • MonoずFluxは、メ゜ッドチェヌンによっお非同期の凊理フロヌを定矩し、**subscribe()**が呌ばれるたでデヌタは流れ始めない怠惰な実行。
  • バックプレッシャヌは、デヌタの流れの速床をコンシュヌマヌ偎が制埡する仕組みであり、システムの安定性を保぀。

🔔 次回予告

これで、Javaのリアクティブプログラミングの栞心に觊れるこずができたした。

次回は、党50回講座の総仕䞊げずしお、これたで孊んだ知識を統合し、Spring Bootアプリケヌションの最終的な性胜チュヌニングず改善に関する総たずめを行いたす。

次回【第49回】総仕䞊げ〜Spring Bootの最終性胜チュヌニングず改善ポむント〜 にご期埅ください

コメント

タむトルずURLをコピヌしたした