Netflix 假装 - 通过微服务传播状态和异常

2022-09-01 17:24:27

我正在使用Netflix Feign调用微服务A的一个操作到微服务B的其他操作,该操作使用Spring Boot验证代码。

微服务 B 的操作会在验证失败的情况下引发异常。然后我在微服务中处理并返回一个(422),如下所示:HttpStatus.UNPROCESSABLE_ENTITY

@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通过微服务传播状态和例外的最佳方式或技术是什么?


答案 1

你可以使用假象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);
    }

}

对于弹簧要拾取错误解码器,您必须将其放在AppplicationContext上:

@Bean
public MyErrorDecoder myErrorDecoder() {
  return new MyErrorDecoder();
}

答案 2

我为一个小库做的无耻插件,它使用反射根据响应正文中返回的错误代码动态重新抛出已检查的异常(如果它们在Feign接口上,则取消选中)。

有关自述文件的更多信息 : https://github.com/coveo/feign-error-decoder


推荐