Mav*_*arn 5 distributed-transactions hystrix microservices spring-cloud spring-cloud-netflix
我正在使用spring cloud来实现我的微服务系统,一个售票平台.场景是,有一个zuul代理,一个eureka注册表和3个服务:用户服务,订单服务和票务服务.服务使用假装声明式REST客户端相互通信.
现在有一个买票的功能,主要流程如下:
1.订单服务接受请求创建订单
2.订单服务创建订单实体具有挂单状态.
3.订购服务呼叫用户服务来处理用户付费.
4.订购服务电话票务服务以更新用户票证.
5.订单服务将订单实体更新为FINISHED.
我想Hystrix Fallback用来实现交易.例如,如果付款流程已完成,但在票证移动期间发生了一些错误.如何尊重用户付款和订单状态.因为用户付款是在其他服务中.
以下是我目前的解决方案,我不确定它是否合适.或者还有其他更好的方法来做到这一点.
首先,OrderResource:
@RestController
@RequestMapping("/api/order")
public class OrderResource {
@HystrixCommand(fallbackMethod = "createFallback")
@PostMapping(value = "/")
public Order create(@RequestBody Order order) {
return orderService.create(order);
}
private Order createFallback(Order order) {
return orderService.createFallback(order);
}
}
Run Code Online (Sandbox Code Playgroud)
然后是OrderService:
@Service
public class OrderService {
@Transactional
public Order create(Order order) {
order.setStatus("PENDING");
order = orderRepository.save(order);
UserPayDTO payDTO = new UserPayDTO();
userCompositeService.payForOrder(payDTO);
order.setStatus("PAID");
order = orderRepository.save(order);
ticketCompositeService.moveTickets(ticketIds, currentUserId);
order.setStatus("FINISHED");
order = orderRepository.save(order);
return order;
}
@Transactional
public Order createFallback(Order order) {
// order is the object processed in create(), there is Transaction in create(), so saving order will be rollback,
// but the order instance still exist.
if (order.getId() == null) { // order not saved even.
return null;
}
UserPayDTO payDTO = new UserPayDTO();
try {
if (order.getStatus() == "FINISHED") { // order finished, must be paid and ticket moved
userCompositeService.payForOrderFallback(payDTO);
ticketCompositeService.moveTicketsFallback(getTicketIdList(order.getTicketIds()), currentUserId);
} else if (order.getStatus() == "PAID") { // is paid, but not sure whether has error during ticket movement.
userCompositeService.payForOrderFallback(payDTO);
ticketCompositeService.moveTicketsFallback(getTicketIdList(order.getTicketIds()), currentUserId);
} else if (order.getStatus() == "PENDING") { // maybe have error during payment.
userCompositeService.payForOrderFallback(payDTO);
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
order.setStatus("FAILED");
orderRepository.save(order); // order saving is rollbacked during create(), I save it here to trace the failed orders.
return order;
}
}
Run Code Online (Sandbox Code Playgroud)
这里的一些关键点是:
@HystrixCommand在OrderResource.create(order)方法中使用,具有fallback功能. order使用所使用的实例 OrderResource.create(order).虽然这种持久性order将得到支持.但是,此实例中的数据仍可用于检查运行情况. ticketCompositeService并且userCompositeService是假装客户.对于假装客户端方法payForOrder(),还有另一种payForOrderFallback()回退方法. try/catch的ticketCompositeService,并userCompositeService呼吁,以确保订单将反正与"失败"的状态被保存.似乎这个解决方案可以在大多数时间使用.除此之外,在回退功能中,如果存在一些错误userCompositeService.payForOrderFallback(payDTO);,则不会调用以下复合服务调用.
而另一个问题是,我认为这太复杂了.
因此,对于这种情况,我应该如何正确有效地实现dist事务.任何建议或建议都会有所帮助.谢谢.
在 Hystrix 回退中编写补偿逻辑是危险的,因为不涉及持久性。
这种方法不提供任何弹性。由于涉及外部各方,来自数据库的 ACID 保证在这里是不够的,并且 Hystrix 回退不会保护您免受代码之外的任何内容的影响。
例如,如果您的解决方案kill -9在付款完成后遇到中断(例如停电或简单的情况),您将丢失订单和补偿逻辑,这意味着订单将被支付,但不会出现在数据库中。
更具弹性的方法将涉及任何流行的消息代理来进行事件驱动的交付,并在处理逻辑中进行一些重复数据删除,以确保在中断后重新交付事件时提供一次性的服务质量。
| 归档时间: |
|
| 查看次数: |
1641 次 |
| 最近记录: |