apache / servicecomb-pack

Apache ServiceComb Pack is an eventually data consistency solution for micro-service applications. ServiceComb Pack currently provides TCC and Saga distributed transaction co-ordination solutions by using Alpha as a transaction coordinator and Omega as an transaction agent .
https://servicecomb.apache.org/
Apache License 2.0
1.93k stars 435 forks source link

分布式事务优雅shut down服务问题 #643

Open tnessn opened 4 years ago

tnessn commented 4 years ago

关闭服务之后,不能调用补偿,即使多实例的情况下,关闭其中一个实例,也不能调用补偿

WillemJiang commented 4 years ago

你的问题场景能具体描述一下吗?如果是分布式事务参与者服务实例退出,Omega是需要在Alpha注销的。目前Alpha在调用Omega的补偿方法是通过CompositeOmegaCallback中的compensate方法, 现在的实现还是绑定了具体的实例, 针对你的问题是可以进行相关的扩展加载不同实例的选择。

Richhardbranson commented 4 years ago

服务A call 服务B
服务B代码 如下:

        @Transactional
    @Compensable(compensationMethod = "cancel",retries=5)
    @Override
    @DtIdempotent
    public void updateUserCoinWallet(UpdateUserCoinWalletReq req) {
        logger.error("钱包【uid={},coinId={}】,begin" +
                "更新钱包,globalTxId={}", req.getUid(),req.getCoinId(),req.getGlobalTxId()) ;
        List<String> keys = new ArrayList<>();
        List<Object> argList = new ArrayList<>();
                ... ...
        }
         @Transactional
     @DtIdempotent
     public void cancel(UpdateUserCoinWalletReq req) {
         logger.error("钱包【uid={},coinId={}】,撤销更新,globalTxId={}",  req.getUid(),req.getCoinId(),req.getGlobalTxId()) ;
        List<String> keys = new ArrayList<>();
        List<String> argList = new ArrayList<>();
        ... ...
         }

服务A中通过SagaStart注解 启动saga事务管理。

服务B 只配置一个实例,在进行重启的时候(启动时长约1分钟) ,重启完成后发现部分事务没有补偿成功。

这种情况是否在服务B端有什么处理机制需要做改进,避免这种情况发生。

zhfeng commented 4 years ago

@DtIdempotent这个注解是在怎么使用的?您所指的优雅shutdown是说在服务B重启的时候,要保证所有的outstanding transaction都是已完成或者已补偿的状态?

tnessn commented 4 years ago

@DtIdempotent这个注解是在怎么使用的?您所指的优雅shutdown是说在服务B重启的时候,要保证所有的outstanding transaction都是已完成或者已补偿的状态?

这个是我自定义的注解,实现幂等的

zhfeng commented 4 years ago

OK, 那你想实现的Graceful shutdown是在服务重启的时候,要保证所有的outstanding transaction都是已完成或者已补偿的状态 ?

tnessn commented 4 years ago

OK, 那你想实现的Graceful shutdown是在服务重启的时候,要保证所有的outstanding transaction都是已完成或者已补偿的状态 ?

是的,目前重启之后会补偿之前的事务吗?我测试了之后是不行的

zhfeng commented 4 years ago

现在补偿采用的方式是grpc回调,目前应该是不支持对多omega实例。@WillemJiang,是这样的吗?

zhfeng commented 4 years ago

@Richhardbranson Alpha端有一个rest api的接口,你看看能不能通过接口查询到?

WillemJiang commented 4 years ago

多个Omega的支持可以通过查询注册的客户端来实现,如果是多个Alpha的情况下处理比较复杂,这块我们还没有实现, @tnessn @Richhardbranson 有兴趣做一下吗?我会给出相关的指导的。 另外建议使用Saga 状态机模式 ,有关数据接口的实现我们不打算提供支持了。

状态机模式下, 查询事件的API

WillemJiang commented 4 years ago

现在补偿采用的方式是grpc回调,目前应该是不支持对多omega实例。@WillemJiang,是这样的吗?

单个Alpha 多个Omega很容易实现,只需要修改我之前提到的那块代码就可以了。

Richhardbranson commented 4 years ago

我们已经切换到状态机模式下,在状态机模式下可以方便的查看到事务的执行情况。在这种模式下,我们再次对omega所在服务进行重启操作。出现了5个suspended的事务。 都是TxAbortEvent 执行超时。这种情况下要保证事务的最终一致性,需要人为干预。UI是没有这个功能的,是否有API可以实现触发。

image

zhfeng commented 4 years ago

@WillemJiang good catch ! I think it is worth to raise an issue for changing these codes ?

zhfeng commented 4 years ago

@Richhardbranson feel free to raise an issue on SCB !

coolbeevip commented 4 years ago

我们已经切换到状态机模式下,在状态机模式下可以方便的查看到事务的执行情况。在这种模式下,我们再次对omega所在服务进行重启操作。出现了5个suspended的事务。 都是TxAbortEvent 执行超时。这种情况下要保证事务的最终一致性,需要人为干预。UI是没有这个功能的,是否有API可以实现触发。

image

在界面实现失败事务的人为干预是一个不错的想法,我下一步正策划实现这个功能,目前还没有开始,有兴趣一起参与吗?

我创建了 JIRA https://issues.apache.org/jira/browse/SCB-1852 跟踪这个问题

Richhardbranson commented 4 years ago

另外还有一点建议。因为各种场景下,异常的情况是有很多的。哪些类别的异常可以自动进行补偿,建议可以进行可扩展的定义。这样对与整个系统的实用性会有很大增强。是否你们已经有考虑。

WillemJiang commented 4 years ago

自动化补偿这块在Alpha端是调用compensate方法。如果能够恢复成功的,就自动恢复了,如果恢复不成功,还是需要人为参与的。 @Richhardbranson 不知道你提到的扩展定义是什么?能详细说明一下吗?

lastboy1228 commented 4 years ago

补偿方法的参数,是缓存在omega实例的内存里的,实例一旦停止,就无法补偿了。只能让omega先不接收新的请求(手动从注册中心或nginx下线),并等已有事务回调全部完毕,才能够优雅shutwown

WillemJiang commented 4 years ago

了解了, @lastboy1228 这块主要shutdown实例的过程中,需要Omega做一些额外处理, 你有兴趣提供补丁吗?