26

私はNetflix Feignを使用して、マイクロサービスAの1つの操作をマイクロサービスBの他の操作に呼び出し、Spring Bootを使用してコードを検証しています。

検証がうまくいかなかった場合、マイクロサービス B の操作は例外をスローします。HttpStatus.UNPROCESSABLE_ENTITY次に、マイクロサービスで処理し、次のように (422)を返します。

@ExceptionHandler({
       ValidateException.class
    })
    @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
    @ResponseBody
    public Object validationException(final HttpServletRequest request, final validateException exception) {
        log.error(exception.getMessage(), exception);
        error.setErrorMessage(exception.getMessage());
        error.setErrorCode(exception.getCode().toString());
        return error;
    }

したがって、マイクロサービス A が次のようにインターフェイスで B を呼び出すと、次のようになります。

@Headers("Content-Type: " + MediaType.APPLICATION_JSON_UTF8_VALUE)
@RequestLine("GET /other")
void otherOperation(@Param("other")  String other );

@Headers("Content-Type: " + MediaType.APPLICATION_JSON_UTF8_VALUE)
@RequestLine("GET /code/validate")
Boolean validate(@Param("prefix") String prefix);

static PromotionClient connect() {

    return Feign.builder()
        .encoder(new GsonEncoder())
        .decoder(new GsonDecoder())
        .target(PromotionClient.class, Urls.SERVICE_URL.toString());
}

検証に失敗すると、次のメッセージとともに内部エラー 500 が返されます。

{
  "timestamp": "2016-08-05T09:17:49.939+0000",
  "status": 500,
  "error": "Internal Server Error",
  "exception": "feign.FeignException",
  "message": "status 422 reading Client#validate(String); content:\n{\r\n  \"errorCode\" : \"VALIDATION_EXISTS\",\r\n  \"errorMessage\" : \"Code already exists.\"\r\n}",
  "path": "/code/validate"
}

しかし、マイクロサービス操作 B と同じものを返す必要があります。

Netflix Feign を使用してマイクロサービスを介してステータスと例外を伝達するための最良の方法または手法はどれですか?

4

6 に答える 6

25

あなたは偽物を使うことができますErrorDecoder

https://github.com/OpenFeign/feign/wiki/Custom-error-handling

ここに例があります

public class MyErrorDecoder implements ErrorDecoder {

    private final ErrorDecoder defaultErrorDecoder = new Default();

    @Override
    public Exception decode(String methodKey, Response response) {
        if (response.status() >= 400 && response.status() <= 499) {
            return new MyBadRequestException();
        }
        return defaultErrorDecoder.decode(methodKey, response);
    }

}

春に ErrorDecoder を取得するには、それを ApplicationContext に配置する必要があります。

@Bean
public MyErrorDecoder myErrorDecoder() {
  return new MyErrorDecoder();
}
于 2016-08-05T13:43:27.487 に答える
4

私が行った小さなライブラリの恥知らずなプラグインは、リフレクションを使用して、応答の本文で返されたエラー コードに基づいて、チェックされた例外を動的に再スローします (Feign インターフェース上にある場合はチェックされません)。

Readme の詳細: https://github.com/coveo/feign-error-decoder

于 2016-12-14T19:12:07.153 に答える
1

カスタム例外マッパーを作成して登録します。応答をカスタマイズできます。

完全な例はこちら

public class GenericExceptionMapper implements ExceptionMapper<Throwable> {

    @Override
    public Response toResponse(Throwable ex) {
        return Response.status(500).entity(YOUR_RETURN_OBJ_HERE).build();
    }

}
于 2016-08-05T13:48:14.047 に答える
0

私たちがしていることは次のとおりです。

両方のマイクロサービスで例外を含む共通の jar を共有します。

1.) マイクロサービスでは、DTO クラスへの変換例外により、ErrorInfo と言うことができます。カスタム例外のすべての属性と、例外クラス名を含む String exceptionType が含まれます。

2.) マイクロサービス B で受信されると、マイクロサービス B の ErrorDecoder によって処理され、以下のように exceptionType から例外オブジェクトを作成しようとします。

@Override
public Exception decode(String methodKey, Response response) {       

ErrorInfo errorInfo = objectMapper.readValue(details, ErrorInfo.class);
Class exceptionClass;

Exception decodedException;

try {

    exceptionClass = Class.forName(errorInfo.getExceptionType());  

    decodedException = (Exception) exceptionClass.newInstance();

    return decodedException;

 }

 catch (ClassNotFoundException e) {

    return new PlatformExecutionException(details, errorInfo);

 }
  return defaultErrorDecoder.decode(methodKey, response);
 }
于 2018-01-24T15:29:54.667 に答える