我正在设计一个服务外观,我有一个方法签名,看起来像这样:
public Policy getPolicy(long policyId) throws PolicyNotFoundException如果没有不良事件发生,则返回一个Policy对象(简单POJO)。如果未找到请求的策略,则会抛出检查的异常PolicyNotFoundException (仅作为参考-当涉及到应用程序内的异常处理的最佳实践时,我们遵循this article )。
服务外观层(在本例中为Spring MVC RestController)之上的层知道如何处理这样的PolicyNotFoundException并返回适当的有效负载。
我正在尝试通过这样的方式将其合并到HystrixCommand中:
@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之外的任何事情。这里所需的任何内容都应该在此服务外观层中捕获。
任何帮助都将不胜感激。谢谢!
发布于 2016-11-10 22:04:25
因此,基于@spencergibb给出的链接-我可能在升级到Hystrix 1.5.7之后找到了解决方案。此代码按预期工作
PolicyRestController.java
@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
public interface PolicyService {
@Cacheable("allPolicies")
public List<Policy> getPolicies();
@Cacheable("policies")
public Policy getPolicy(long policyId) throws PolicyNotFoundException;
}PolicyServiceImpl.java:
@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);
}
}发布于 2016-11-09 22:01:18
这是hystrix的默认行为。“如果命令有回退,则只会将触发回退逻辑的第一个异常传播到调用方”
请参阅错误传播部分here。
发布于 2016-11-11 23:22:21
虽然您的解决方案可能对您有效,但我注意到您的代码中有一些奇怪的地方(我无法检查我的假设,所以我想请您检查一下)。
@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);
}
}https://stackoverflow.com/questions/40495259
复制相似问题