spring-cloud - 如何基于Spring Cloud架构师实现带有hystrix fallback的分布式事务

标签 spring-cloud microservices distributed-transactions hystrix 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);
  }
}

然后是 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;
    }
}

这里的一些关键点是:
  • 使用 @HystrixCommandOrderResource.create(order)方法,使用 fallback功能。
  • 如果创建有错误,order OrderResource.create(order) 中使用的实例将在回退功能中再次使用。虽然这个order的坚持将被回滚。但本实例中的数据仍可用于检查运行情况。
  • 所以我使用状态:'PENDING', 'PAID', 'FINISHED' 来检查是否进行了一些服务调用。
  • ticketCompositeServiceuserCompositeService是一个假客户。假客户端方法payForOrder() ,还有一种方法payForOrderFallback()为后备。
  • 我需要确保可以多次调用回退方法。
  • 我加try/catchticketCompositeServiceuserCompositeService调用,以确保订单将以“失败”状态保存。

  • 似乎这个解决方案在大多数情况下都可以工作。除此之外,在回退函数中,如果 userCompositeService.payForOrderFallback(payDTO); 中出现错误,则不会调用以下复合服务调用。

    而且,另一个问题是,我认为它太复杂了。

    那么,对于这种场景,我应该如何正确有效地实现 dist 事务。任何建议或意见都会有所帮助。谢谢。

    最佳答案

    在 Hystrix 回退中编写补偿逻辑是危险的,因为不涉及持久性。

    这种方法不提供任何弹性。由于涉及外部方,因此数据库的 ACID 保证在这里是不够的,而且 Hystrix 回退不会保护您免受任何不属于您的代码的影响。

    例如,如果您的解决方案在付款完成后遇到中断(例如,停电或简单的 kill -9),您将丢失订单和补偿逻辑,这意味着订单将被支付,但不会出现在数据库中。

    更具弹性的方法将涉及用于事件驱动交付的任何流行消息代理和处理逻辑中的一些重复数据删除,以确保在中断后重新交付事件时的一次性服务质量。

    关于spring-cloud - 如何基于Spring Cloud架构师实现带有hystrix fallback的分布式事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44065186/

    相关文章:

    java - 云异常 : No suitable cloud connector found

    java - Spring Cloud Hystrix : FallbackMethod not invoked

    java - 多实例 Activiti 6 设置中的作业取消

    Java 使用 TransactionManager 实现两阶段提交

    java - 如何让spring-cloud zuul为不同的服务使用不同的线路

    spring-boot - spring cloud stream - 消费者群体绑定(bind)

    docker - 试图了解 Kubernetes 工作节点和 Pod 与 Docker 的比较 "Service"

    microservices - 如何在微服务架构中构建报告?

    java - 为什么我使用 Spring Integration/JtaTransactionManager 看到多个事务

    java - 处理 Apache ServiceComb 补偿方法中的附加数据