Spring Cloud サーキットブレーカーガイド

このガイドでは、Spring Cloud Circuit Breaker を使用して潜在的に失敗するメソッド呼び出しにサーキットブレーカーを適用するプロセスについて説明します。

構築するもの

メソッド呼び出しが失敗したときに、サーキットブレーカーパターン (英語) を使用して機能を適切に低下させるマイクロサービスアプリケーションを構築します。サーキットブレーカーパターンを使用すると、関連するサービスに障害が発生した場合でもマイクロサービスの動作を継続できるため、障害の連鎖を防ぎ、障害が発生したサービスに復旧する時間を与えることができます。

必要なもの

本ガイドの完成までの流れ

ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。

最初から始めるには、Spring Initializr から開始に進みます。

基本スキップするには、次の手順を実行します。

完了したときは、gs-cloud-circuit-breaker/complete のコードに対して結果を確認できます。

Spring Initializr から開始

この事前に初期化されたプロジェクト (書店アプリケーションの場合) またはこの事前に初期化されたプロジェクト (読書アプリケーションの場合) を使用して、生成 をクリックして ZIP ファイルをダウンロードできます。このプロジェクトは、このチュートリアルの例に適合するように構成されています。

プロジェクトを手動で初期化するには:

  1. IDE のメニューまたはブラウザーから Spring Initializr を開きます。アプリケーションに必要なすべての依存関係を取り込み、ほとんどのセットアップを行います。

  2. Gradle または Maven のいずれかと、使用する言語を選択します。このガイドは、Java を選択したことを前提としています。

  3. 依存関係をクリックし、Spring リアクティブ Web (サービスアプリケーションの場合) または Spring リアクティブ Web および Resilience4J (クライアントアプリケーションの場合) を選択します。

  4. 生成をクリックします。

  5. 結果の ZIP ファイルをダウンロードします。これは、選択して構成された Web アプリケーションのアーカイブです。

EclipseIntelliJ のような IDE は新規プロジェクト作成ウィザードから Spring Initializr の機能が使用できるため、手動での ZIP ファイルのダウンロードやインポートは不要です。
プロジェクトを Github からフォークして、IDE または他のエディターで開くこともできます。

サーバーマイクロサービスアプリケーションのセットアップ

Bookstore サービスには単一のエンドポイントがあります。これは /recommended でアクセスでき、(簡単にするために) 推奨される読書リストを String の Mono として返します。

BookstoreApplication.java のメインクラスは次のようになります。

bookstore/src/main/java/hello/BookstoreApplication.java

package hello;

import reactor.core.publisher.Mono;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
@SpringBootApplication
public class BookstoreApplication {

  @RequestMapping(value = "/recommended")
  public Mono<String> readingList(){
    return Mono.just("Spring in Action (Manning), Cloud Native Java (O'Reilly), Learning Spring Boot (Packt)");
  }

  public static void main(String[] args) {
    SpringApplication.run(BookstoreApplication.class, args);
  }
}

@RestController アノテーションは、@Controller と同様に BookstoreApplication をコントローラークラスとしてマークし、このクラスの @RequestMapping メソッドが @ResponseBody でアノテーションが付けられているかのように動作することも保証します。つまり、このクラスの @RequestMapping メソッドの戻り値は、元の型から適切に自動的に変換され、レスポンス本文に直接書き込まれます。

このアプリケーションをクライアントサービスアプリケーションと一緒にローカルで実行するには、src/main/resources/application.properties で、ブックストアサービスがクライアントと競合しないように server.port を設定します。

bookstore/src/main/resources/application.properties

server.port=8090

クライアントマイクロサービスアプリケーションを設定する

Reading アプリケーションは、Bookstore アプリケーションのフロントエンドです。/to-read で読書リストを表示でき、その読書リストは Bookstore サービスアプリケーションから取得されます。

reading/src/main/java/hello/ReadingApplication.java

package hello;

import reactor.core.publisher.Mono;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.client.WebClient;

@RestController
@SpringBootApplication
public class ReadingApplication {

  @RequestMapping("/to-read")
    public Mono<String> toRead() {
      return WebClient.builder().build()
      .get().uri("http://localhost:8090/recommended").retrieve()
      .bodyToMono(String.class);
  }

  public static void main(String[] args) {
    SpringApplication.run(ReadingApplication.class, args);
  }
}

書店からリストを取得するには、Spring の WebClient クラスを使用します。WebClient は、指定された Bookstore サービスの URL に対して HTTP GET リクエストを行い、その結果を String の Mono として返します。(Spring を使用して WebClient を使用する RESTful サービスを利用する方法の詳細については、WebFlux REST API と WebClient ガイドを参照してください。)

server.port プロパティを src/main/resources/application.properties に追加します。

reading/src/main/resources/application.properties

server.port=8080

これで、ブラウザーで Reading アプリケーションの /to-read エンドポイントにアクセスし、リーディングリストを表示できるようになりました。ただし、Bookstore アプリケーションに依存しているため、何かが発生した場合、Reading アプリケーションが Bookstore にアクセスできない場合、リストがなく、ユーザーは厄介な HTTP 500 エラーメッセージを受け取ります。

サーキットブレーカーパターンを適用する

Spring Cloud のサーキットブレーカーライブラリは、サーキットブレーカーパターンの実装を提供します。サーキットブレーカーでメソッド呼び出しをラップすると、Spring Cloud Circuit Breaker はそのメソッドの呼び出しの失敗を監視し、失敗が指定されたしきい値に達すると、Spring Cloud Circuit Breaker が回路を開き、後続のコールは自動的に失敗します。回線が開いている間、Spring Cloud Circuit Breaker は呼び出しをメソッドにリダイレクトし、それらは指定されたフォールバックメソッドに渡されます。

Spring Cloud Circuit Breaker は、Resilience4J、Hystrix、Sentinal、Spring Retry など、さまざまなサーキットブレーカーの実装をサポートしています。このガイドでは、Resilience4J 実装を使用します。この実装を使用するには、アプリケーションのクラスパスに spring-cloud-starter-circuitbreaker-reactor-resilience4j を追加する必要があります。

reading/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.5.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>spring-cloud-circuit-breaker-reading</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-cloud-circuit-breaker-reading</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>17</java.version>
		<spring-cloud.version>2025.0.0</spring-cloud.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-webflux</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>io.projectreactor</groupId>
			<artifactId>reactor-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

reading/build.gradle

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.5.0'
	id 'io.spring.dependency-management' version '1.1.5'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
	mavenCentral()
}

ext {
	springCloudVersion = '2025.0.0'
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-webflux'
	implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'io.projectreactor:reactor-test'
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
}

tasks.named('test') {
	useJUnitPlatform()
}

Spring Cloud Circuit Breaker は ReactiveCircuitBreakerFactory と呼ばれるインターフェースを提供します。これを使用して、アプリケーション用の新しいサーキットブレーカーを作成できます。このインターフェースの実装は、アプリケーションのクラスパスにあるスターターに基づいて自動構成されます。これで、このインターフェースを使用して Bookstore アプリケーションへの API 呼び出しを行う新しいサービスを作成できます。

reading/src/main/java/hello/BookService.java

package hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;

import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreaker;
import org.springframework.cloud.client.circuitbreaker.ReactiveCircuitBreakerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

@Service
public class BookService {

  private static final Logger LOG = LoggerFactory.getLogger(BookService.class);


  private final WebClient webClient;
  private final ReactiveCircuitBreaker readingListCircuitBreaker;

  public BookService(ReactiveCircuitBreakerFactory circuitBreakerFactory) {
    this.webClient = WebClient.builder().baseUrl("http://localhost:8090").build();
    this.readingListCircuitBreaker = circuitBreakerFactory.create("recommended");
  }

  public Mono<String> readingList() {
    return readingListCircuitBreaker.run(webClient.get().uri("/recommended").retrieve().bodyToMono(String.class), throwable -> {
      LOG.warn("Error making request to book service", throwable);
      return Mono.just("Cloud Native Java (O'Reilly)");
    });
  }
}

ReactiveCircuitBreakerFactory には create と呼ばれる単一のメソッドがあり、これを使用して新しいサーキットブレーカーを作成できます。サーキットブレーカーができたら、あとは run を呼び出すだけです。run は Mono または Flux とオプションの Function を使用します。オプションの Function パラメーターは、問題が発生した場合のフォールバックとして機能します。このサンプルでは、フォールバックは String Cloud Native Java (O ’ Reilly) を含む Mono を返します。

新しいサービスを配置したら、この新しいサービスを使用するように ReadingApplication のコードを更新できます。

reading/src/main/java/hello/ReadingApplication.java

package hello;

import reactor.core.publisher.Mono;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.reactive.function.client.WebClient;

@RestController
@SpringBootApplication
public class ReadingApplication {

  @Autowired
  private BookService bookService;

  @RequestMapping("/to-read")
  public Mono<String> toRead() {
    return bookService.readingList();
  }

  public static void main(String[] args) {
    SpringApplication.run(ReadingApplication.class, args);
  }
}

試してみよう

Bookstore サービスと Reading サービスの両方を実行し、ブラウザーを開いて localhost:8080/to-read の Reading サービスを開きます。完全な推奨読書リストが表示されます。

Spring in Action (Manning), Cloud Native Java (O'Reilly), Learning Spring Boot (Packt)

Bookstore アプリケーションをシャットダウンします。私たちのリストのソースはなくなりましたが、Hystrix と Spring Cloud Netflix のおかげで、ギャップに立つための信頼できる省略されたリストがあります。君は見るべきだ:

Cloud Native Java (O'Reilly)

要約

おめでとう! サーキットブレーカーパターンを使用してカスケードエラーから保護し、失敗する可能性のある呼び出しに対してフォールバック動作を提供する Spring アプリケーションを開発しました。

関連事項

新しいガイドを作成したり、既存のガイドに貢献したいですか? 投稿ガイドラインを参照してください [GitHub] (英語)

すべてのガイドは、コード用の ASLv2 ライセンス、およびドキュメント用の Attribution、NoDerivatives creative commons ライセンス (英語) でリリースされています。

コードを入手する