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

Pau*_*Pau 20 java spring spring-boot microservices netflix-feign

我正在使用Netflix Feign将微服务A的一个操作调用到微服务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;
    }
Run Code Online (Sandbox Code Playgroud)

因此,当微服务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());
}
Run Code Online (Sandbox Code Playgroud)

并且验证失败它返回内部错误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"
}
Run Code Online (Sandbox Code Playgroud)

但我需要返回与微服务操作B相同的操作.

使用Netflix Feign通过微服务传播状态和例外的最佳方式或技术是什么?

Mat*_*nkt 21

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

}
Run Code Online (Sandbox Code Playgroud)

要使spring接收ErrorDecoder,您必须将它放在ApplicationContext上:

@Bean
public MyErrorDecoder myErrorDecoder() {
  return new MyErrorDecoder();
}
Run Code Online (Sandbox Code Playgroud)