首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >由Hystrix回退引发的捕获异常?

由Hystrix回退引发的捕获异常?
EN

Stack Overflow用户
提问于 2016-11-09 03:49:11
回答 4查看 14.9K关注 0票数 1

我正在设计一个服务外观,我有一个方法签名,看起来像这样:

代码语言:javascript
复制
public Policy getPolicy(long policyId) throws PolicyNotFoundException

如果没有不良事件发生,则返回一个Policy对象(简单POJO)。如果未找到请求的策略,则会抛出检查的异常PolicyNotFoundException (仅作为参考-当涉及到应用程序内的异常处理的最佳实践时,我们遵循this article )。

服务外观层(在本例中为Spring MVC RestController)之上的层知道如何处理这样的PolicyNotFoundException并返回适当的有效负载。

我正在尝试通过这样的方式将其合并到HystrixCommand中:

代码语言:javascript
复制
@HystrixCommand(groupKey = "PolicyService", fallbackMethod = "getPolicySafe", ignoreExceptions = { PolicyNotFoundException.class })
public Policy getPolicy(long policyId) throws PolicyNotFoundException {
    LOGGER.info("Getting policy {}", policyId);

    // Simulate some error condition for testing purposes
    throw new RuntimeException("Something happened!");
}

private Policy getPolicySafe(long policyId, Throwable t) throws PolicyNotFoundException {
    LOGGER.warn("Falling back to circuit-breaker for getting policy {}", policyId, t);
    throw new PolicyNotFoundException(policyId);
}

基本上,我想让我的断路器表现得就像原来的查找没有找到策略一样。然而,我遇到的问题是,我从回退方法中抛出的异常在翻译过程中迷失了方向。我最终在上面的层中看到的异常是command方法抛出的RuntimeException,而不是fallback方法抛出的异常。有什么办法可以解决这个问题吗?我也不想更改原始方法的契约,也不想让它上面的层知道在策略找不到的情况下必须捕获PolicyNotFoundException之外的任何事情。这里所需的任何内容都应该在此服务外观层中捕获。

任何帮助都将不胜感激。谢谢!

EN

回答 4

Stack Overflow用户

发布于 2016-11-10 22:04:25

因此,基于@spencergibb给出的链接-我可能在升级到Hystrix 1.5.7之后找到了解决方案。此代码按预期工作

PolicyRestController.java

代码语言:javascript
复制
@RestController
@RequestMapping("/policies")
public class PoliciesApi {
  private static final Logger LOGGER = LoggerFactory.getLogger(PoliciesApi.class);

  @Autowired
  private PolicyService policyService;

  @RequestMapping(value = "/{policyId}", method = RequestMethod.GET, produces = { MediaTypes.POLICY_JSON_VALUE, MediaTypes.POLICY_XML_VALUE })
  public Policy getPolicy(@PathVariable long policyId) {
    try {
      // This just shown for simplicity. There is more to this method (input validation/etc)
      return this.policyService.getPolicy(policyId);
    }
    catch (PolicyNotFoundException ex) {
      // NotFoundException is a RuntimeException annotated with @ResponseStatus(HttpStatus.NOT_FOUND)
      // So the service returns a 404 to the client
      LOGGER.info("Policy {} wasn't found", ex.getPolicyId(), ex);
      throw new NotFoundException(String.format("Policy %s was not found", ex.getPolicyId()));
    }
  }
}

PolicyService.java

代码语言:javascript
复制
public interface PolicyService {
    @Cacheable("allPolicies")
    public List<Policy> getPolicies();

    @Cacheable("policies")
    public Policy getPolicy(long policyId) throws PolicyNotFoundException;
}

PolicyServiceImpl.java:

代码语言:javascript
复制
@Service
public class PolicyServiceImpl implements PolicyService {
  @HystrixCommand(groupKey = "PolicyService", fallbackMethod = "getPolicySafe", ignoreExceptions = { PolicyNotFoundException.class })
  public Policy getPolicy(long policyId) throws PolicyNotFoundException {
    LOGGER.info("Getting policy {}", policyId);

    // Simulate some error condition for testing purposes
    throw new RuntimeException("Something happened!");
  }

  @HystrixCommand(groupKey = "PolicyService", ignoreExceptions = { PolicyNotFoundException.class }, raiseHystrixExceptions = { HystrixException.RUNTIME_EXCEPTION })
  private Policy getPolicySafe(long policyId) throws PolicyNotFoundException {
    // Here is we hit our fallback we want to log a warning & simply act as if the policy wasn't found by throwing the same contingency exception as the API does
    LOGGER.warn("Falling back to circuit-breaker for getting policy {}", policyId);

    throw new PolicyNotFoundException(policyId);
  }
}
票数 4
EN

Stack Overflow用户

发布于 2016-11-09 22:01:18

这是hystrix的默认行为。“如果命令有回退,则只会将触发回退逻辑的第一个异常传播到调用方”

请参阅错误传播部分here

票数 1
EN

Stack Overflow用户

发布于 2016-11-11 23:22:21

虽然您的解决方案可能对您有效,但我注意到您的代码中有一些奇怪的地方(我无法检查我的假设,所以我想请您检查一下)。

  1. 尽量避免在代码中使用检查异常,因为它很难维护。
  2. 基于你的代码,你永远不会捕捉到"PolicyNotFoundException“,因为你使用的是raiseHystrixExceptions ={ HystrixException.RUNTIME_EXCEPTION },这意味着你不会得到你的自定义异常,所以HystrixRuntimeException将被传播。试着重写你的代码,如下所示,这样就可以简化代码,也许还能修复一些问题:

代码语言:javascript
复制
@Service
public class PolicyServiceImpl implements PolicyService {
  @HystrixCommand(groupKey = "PolicyService", fallbackMethod = "getPolicySafe")
  public Policy getPolicy(long policyId) throws PolicyNotFoundException {
    LOGGER.info("Getting policy {}", policyId);
    throw new PolicyNotFoundException(); // throw real PolicyNotFoundException if policy is absent for the given id
  }

  @HystrixCommand(groupKey = "PolicyService")
  private Policy getPolicySafe(long policyId) throws PolicyNotFoundException {
    // Here is we hit our fallback we want to log a warning & simply act as if the policy wasn't found by throwing the same contingency exception as the API does
    LOGGER.warn("Falling back to circuit-breaker for getting policy {}", policyId);

    throw new PolicyNotFoundException(policyId);
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40495259

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档