Spring Boot マイクロサービスの高度なエラー処理

Patricia Arquette
リリース: 2024-10-28 19:02:30
オリジナル
509 人が閲覧しました

Advanced Error Handling in Spring Boot Microservices

複雑なマイクロサービスでは、高度なエラー処理は単純な例外ログを超えています。効果的なエラー処理は、信頼性、拡張性、優れたユーザー エクスペリエンスを維持するために非常に重要です。この記事では、分散システムでのエラーの管理、再試行の処理、カスタム エラー応答の作成、デバッグを容易にする方法でのエラーのログ記録の戦略に焦点を当て、Spring Boot マイクロサービスでのエラー処理の高度なテクニックについて説明します。

1. Spring Boot での基本的なエラー処理

Spring Boot での基本的なエラー処理アプローチから始めて、ベースラインを設定しましょう。

1.1 @ControllerAdvice と @ExceptionHandler の使用

Spring Boot は、@ControllerAdvice と @ExceptionHandler を備えたグローバル例外ハンドラーを提供します。この設定により、すべてのコントローラーの例外を 1 か所で処理できるようになります。

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {
        ErrorResponse error = new ErrorResponse("NOT_FOUND", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {
        ErrorResponse error = new ErrorResponse("INTERNAL_SERVER_ERROR", "An unexpected error occurred.");
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
ログイン後にコピー
ログイン後にコピー

ここで、ErrorResponse はカスタム エラー モデルです:

public class ErrorResponse {
    private String code;
    private String message;

    // Constructors, Getters, and Setters
}
ログイン後にコピー
ログイン後にコピー

1.2 一貫したエラー応答を返す

すべての例外が一貫したエラー応答形式 (ErrorResponse など) を返すようにすることで、クライアントがエラーを正しく解釈できるようになります。


2.エラー処理のための高度なテクニック

2.1 エラー ID による一元的なログ記録と追跡

各例外に一意のエラー ID を割り当てると、サービス全体で特定のエラーを追跡するのに役立ちます。デバッグを容易にするために、この ID を例外の詳細と一緒に記録することもできます。

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {
    String errorId = UUID.randomUUID().toString();
    log.error("Error ID: {}, Message: {}", errorId, ex.getMessage(), ex);

    ErrorResponse error = new ErrorResponse("INTERNAL_SERVER_ERROR", 
                                             "An unexpected error occurred. Reference ID: " + errorId);
    return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
ログイン後にコピー
ログイン後にコピー

クライアントは、errorId を含むエラー応答を受け取り、詳細なログに直接リンクしてサポートに報告できます。

2.2 一時的なエラーに対する再試行ロジックの追加

分散システムでは、一時的な問題 (ネットワーク タイムアウトなど) は再試行で解決できます。サービスメソッドの再試行ロジックには Spring の @Retryable を使用します。

セットアップ

まず、Spring Retry の依存関係を pom.xml に追加します。

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
ログイン後にコピー
ログイン後にコピー

次に、@EnableRetry を使用して Spring Retry を有効にし、再試行が必要なメソッドにアノテーションを付けます。

@EnableRetry
@Service
public class ExternalService {

    @Retryable(
        value = { ResourceAccessException.class },
        maxAttempts = 3,
        backoff = @Backoff(delay = 2000))
    public String callExternalService() throws ResourceAccessException {
        // Code that calls an external service
    }

    @Recover
    public String recover(ResourceAccessException e) {
        log.error("External service call failed after retries.", e);
        return "Fallback response due to error.";
    }
}
ログイン後にコピー
ログイン後にコピー

この設定では、メソッドを最大 3 回再試行し、試行の間に 2 秒の遅延を設けます。すべての試行が失敗した場合、リカバリ メソッドがフォールバックとして実行されます。

2.3 マイクロサービスでのフォールバックでの Feign Client の使用

サービス間呼び出しでのエラー処理のために、Feign は再試行とフォールバックを設定する宣言的な方法を提供します。

偽の構成

フォールバック サポートを備えた Feign クライアントを定義します:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {
        ErrorResponse error = new ErrorResponse("NOT_FOUND", ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {
        ErrorResponse error = new ErrorResponse("INTERNAL_SERVER_ERROR", "An unexpected error occurred.");
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
ログイン後にコピー
ログイン後にコピー

このアプローチにより、在庫サービスが利用できない場合に、事前定義された応答で InventoryServiceFallback が開始されます。


3.エラーのログ記録と可観測性

3.1 ELK スタックによる集中ロギング

ELK (Elasticsearch、Logstash、Kibana) スタックを構成して、複数のマイクロサービスからのログを統合します。集中ログ システムを使用すると、サービス間で問題を簡単に追跡し、関連するエラー ID とともにログを表示できます。

たとえば、application.yml でログ パターンを構成します。

public class ErrorResponse {
    private String code;
    private String message;

    // Constructors, Getters, and Setters
}
ログイン後にコピー
ログイン後にコピー

3.2 Spring Cloud Sleuth を使用したトレース ID の追加

分散システムでは、複数のサービスにわたる単一のトランザクションを追跡することが重要です。 Spring Cloud Sleuth は、一意のトレース ID とスパン ID を使用した分散トレースを提供します。

依存関係に Spring Cloud Sleuth を追加します:

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {
    String errorId = UUID.randomUUID().toString();
    log.error("Error ID: {}, Message: {}", errorId, ex.getMessage(), ex);

    ErrorResponse error = new ErrorResponse("INTERNAL_SERVER_ERROR", 
                                             "An unexpected error occurred. Reference ID: " + errorId);
    return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
ログイン後にコピー
ログイン後にコピー

4. REST API のカスタム エラー処理

4.1 カスタム例外クラスの作成

カスタム例外を定義して、より具体的なエラー処理を提供します。

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
ログイン後にコピー
ログイン後にコピー

4.2 カスタムエラー応答構造

構造化され強化されたエラー メッセージの ErrorAttributes を実装して、エラー応答をカスタマイズします。

@EnableRetry
@Service
public class ExternalService {

    @Retryable(
        value = { ResourceAccessException.class },
        maxAttempts = 3,
        backoff = @Backoff(delay = 2000))
    public String callExternalService() throws ResourceAccessException {
        // Code that calls an external service
    }

    @Recover
    public String recover(ResourceAccessException e) {
        log.error("External service call failed after retries.", e);
        return "Fallback response due to error.";
    }
}
ログイン後にコピー
ログイン後にコピー

構成に CustomErrorAttributes を登録して、すべてのエラー応答を自動的にカスタマイズします。

4.3 問題の詳細を含む API エラー応答の標準化 (RFC 7807)

標準化された API エラー構造には問題の詳細形式を使用します。 RFC 7807 に基づいてエラー応答モデルを定義します:

@FeignClient(name = "inventory-service", fallback = InventoryServiceFallback.class)
public interface InventoryServiceClient {
    @GetMapping("/api/inventory/{id}")
    InventoryResponse getInventory(@PathVariable("id") Long id);
}

@Component
public class InventoryServiceFallback implements InventoryServiceClient {

    @Override
    public InventoryResponse getInventory(Long id) {
        // Fallback logic, like returning cached data or an error response
        return new InventoryResponse(id, "N/A", "Fallback inventory");
    }
}
ログイン後にコピー

次に、@ControllerAdvice メソッドからこの構造化された応答を返し、すべての API で一貫したエラー構造を維持します。

logging:
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
ログイン後にコピー

5.レジリエンスのためのサーキットブレーカー

サーキット ブレーカー パターンを統合すると、マイクロサービスが失敗したサービスを繰り返し呼び出すことから保護されます。

Resilience4j サーキットブレーカーの使用
Resilience4j を依存関係に追加します:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
ログイン後にコピー

次に、メソッドをサーキット ブレーカーでラップします。

public class InvalidRequestException extends RuntimeException {
    public InvalidRequestException(String message) {
        super(message);
    }
}
ログイン後にコピー

このセットアップは、複数回失敗すると getInventory の呼び出しを停止し、代わりに inventoryFallback が安全な応答を返します。


結論

Spring Boot マイクロサービスの高度なエラー処理には次のものが含まれます。

集中エラー処理により、一貫した応答と簡素化されたデバッグが実現します。
再試行とサーキット ブレーカーにより、回復力のあるサービス間呼び出しを実現します。
ELK や Sleuth などのツールによる一元的なログ記録とトレーサビリティ
カスタム エラー形式。問題の詳細と構造化されたエラー応答が含まれます。
これらの手法は、マイクロサービスの堅牢性を確保し、一貫した追跡可能なエラー応答を提供しながら、サービス間でのカスケード障害を防止するのに役立ちます。

以上がSpring Boot マイクロサービスの高度なエラー処理の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート