servicecomb-pack
servicecomb-pack copied to clipboard
servicecomb的向前恢复和逆向补偿不可兼得吗?
servicecomb的正向恢复和逆向补偿不可兼得吗?测试的时候发现,配置了向前恢复后,就不会执行逆向补偿方法了。
你配置 @Compensable 的 retries 值是多少?
你配置 @Compensable 的 retries 值是多少?
我配置的是3次,测试发现向前恢复是有做,但是3次重试不成功后,saga直接就结束了,alaph端没有生成补偿命令出来。
你配置 @Compensable 的 retries 值是多少?
我配置的是3次,测试发现向前恢复是有做,但是3次重试不成功后,saga直接就结束了,alaph端没有生成补偿命令出来。
你用的什么版本?是传统模式还是状态机模式?
你配置 @Compensable 的 retries 值是多少?
我配置的是3次,测试发现向前恢复是有做,但是3次重试不成功后,saga直接就结束了,alaph端没有生成补偿命令出来。
你用的什么版本?是传统模式还是状态机模式?
用的是0.6.0的版本,目前用了传统模式,状态机模式需要依赖的外部组件还是比较多。
io.grpc.StatusRuntimeException: CANCELLED: call already cancelled at io.grpc.Status.asRuntimeException(Status.java:517) at io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl.onCompleted(ServerCalls.java:356) at org.apache.servicecomb.pack.alpha.server.tcc.callback.GrpcOmegaTccCallback.disconnect(GrpcOmegaTccCallback.java:51) at org.apache.servicecomb.pack.alpha.server.tcc.GrpcTccEventService.onDisconnected(GrpcTccEventService.java:100) at org.apache.servicecomb.pack.contract.grpc.TccEventServiceGrpc$MethodHandlers.invoke(TccEventServiceGrpc.java:646) at io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.onHalfClose(ServerCalls.java:171) at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:283) at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed.runInContext(ServerImpl.java:707) at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
服务端抛出了异常也很奇怪,出现TCC的Omega回调
以前我一直没有关注过前向恢复,我看了一下代码,如你所说前向恢复可能不会进行补偿,我看了一下前向恢复的类 https://github.com/apache/servicecomb-pack/blob/9064e550c9b754bd61031dc3beae90a5ba34be75/omega/omega-transaction/src/main/java/org/apache/servicecomb/pack/omega/transaction/ForwardRecovery.java 在方法调用前并没有发送 TxStartedEvent,只是在失败后会发送 TxAbortedEvent。
而对于后台查询TxEvent表判断哪些子事务需要补偿时,好想必须找到 TxAbortedEvent 对应的 TxStartedEvent 才会插入一个补偿命令到命令表 COMMAND
至于为什么这么考虑,我也不确定这么做的理由,@WillemJiang 你可以看一下这个问题吗
你配置 @Compensable 的 retries 值是多少?
我配置的是3次,测试发现向前恢复是有做,但是3次重试不成功后,saga直接就结束了,alaph端没有生成补偿命令出来。
你用的什么版本?是传统模式还是状态机模式?
用的是0.6.0的版本,目前用了传统模式,状态机模式需要依赖的外部组件还是比较多。
io.grpc.StatusRuntimeException: CANCELLED: call already cancelled at io.grpc.Status.asRuntimeException(Status.java:517) at io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl.onCompleted(ServerCalls.java:356) at org.apache.servicecomb.pack.alpha.server.tcc.callback.GrpcOmegaTccCallback.disconnect(GrpcOmegaTccCallback.java:51) at org.apache.servicecomb.pack.alpha.server.tcc.GrpcTccEventService.onDisconnected(GrpcTccEventService.java:100) at org.apache.servicecomb.pack.contract.grpc.TccEventServiceGrpc$MethodHandlers.invoke(TccEventServiceGrpc.java:646) at io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.onHalfClose(ServerCalls.java:171) at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:283) at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed.runInContext(ServerImpl.java:707) at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
服务端抛出了异常也很奇怪,出现TCC的Omega回调
你是否也使用了TCC的注解?
你配置 @Compensable 的 retries 值是多少?
我配置的是3次,测试发现向前恢复是有做,但是3次重试不成功后,saga直接就结束了,alaph端没有生成补偿命令出来。
你用的什么版本?是传统模式还是状态机模式?
用的是0.6.0的版本,目前用了传统模式,状态机模式需要依赖的外部组件还是比较多。 io.grpc.StatusRuntimeException: CANCELLED: call already cancelled at io.grpc.Status.asRuntimeException(Status.java:517) at io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl.onCompleted(ServerCalls.java:356) at org.apache.servicecomb.pack.alpha.server.tcc.callback.GrpcOmegaTccCallback.disconnect(GrpcOmegaTccCallback.java:51) at org.apache.servicecomb.pack.alpha.server.tcc.GrpcTccEventService.onDisconnected(GrpcTccEventService.java:100) at org.apache.servicecomb.pack.contract.grpc.TccEventServiceGrpc$MethodHandlers.invoke(TccEventServiceGrpc.java:646) at io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.onHalfClose(ServerCalls.java:171) at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:283) at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed.runInContext(ServerImpl.java:707) at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) 服务端抛出了异常也很奇怪,出现TCC的Omega回调
你是否也使用了TCC的注解?
我没有使用TCC注解。
另外定位到一个问题,servicecomb里面使用了kyro做序列化,我这边定义的参数是没有无参构造器,这个反序列化会有问题。

抱歉,我对 Kyro 序列化的细节不是太了解,但是我记得序列化只用于在Omega和Alpha之间传递框架内固定的几个事件对象,你能提供进一步细节吗
抱歉,我对 Kyro 序列化的细节不是太了解,但是我记得序列化只用于在Omega和Alpha之间传递框架内固定的几个事件对象,你能提供进一步细节吗
我看了服务框架,kyro用于将加了补偿注解的方法的参数序列化,然后作为事件的payload发送到alpha,最后持久化到db,然后补偿的时候,通过grpc,把事件转换的命令推回给omega端(之前上报的payload作为输入),此时,omega会序列化推回的payload,转换为补偿方法调用的入参,这也是你们为什么要求补偿方法和标识的业务逻辑方法函数签名一样的原因,如果这些函数签名的入参对象,如果是没有无参构造器的话,kyro是无法反序列化,会导致抛出序列化失败异常,最后无法完成向后补偿。

抱歉,我对 Kyro 序列化的细节不是太了解,但是我记得序列化只用于在Omega和Alpha之间传递框架内固定的几个事件对象,你能提供进一步细节吗
我看了服务框架,kyro用于将加了补偿注解的方法的参数序列化,然后作为事件的payload发送到alpha,最后持久化到db,然后补偿的时候,通过grpc,把事件转换的命令推回给omega端(之前上报的payload作为输入),此时,omega会序列化推回的payload,转换为补偿方法调用的入参,这也是你们为什么要求补偿方法和标识的业务逻辑方法函数签名一样的原因,如果这些函数签名的入参对象,如果是没有无参构造器的话,kyro是无法反序列化的, 会导致无法执行补偿命令。
明白了,你可以在补偿方法里通过omegaContext.globalTxId()和omegaContext.localTxId()可得到当前分布式事务的全局事务ID及本地事务ID,根据这个ID在去获取你补偿需要的参数,这可能需要业务系统做一些工作。
抱歉,我对 Kyro 序列化的细节不是太了解,但是我记得序列化只用于在Omega和Alpha之间传递框架内固定的几个事件对象,你能提供进一步细节吗
我看了服务框架,kyro用于将加了补偿注解的方法的参数序列化,然后作为事件的payload发送到alpha,最后持久化到db,然后补偿的时候,通过grpc,把事件转换的命令推回给omega端(之前上报的payload作为输入),此时,omega会序列化推回的payload,转换为补偿方法调用的入参,这也是你们为什么要求补偿方法和标识的业务逻辑方法函数签名一样的原因,如果这些函数签名的入参对象,如果是没有无参构造器的话,kyro是无法反序列化的, 会导致无法执行补偿命令。
明白了,你可以在补偿方法里通过omegaContext.globalTxId()和omegaContext.localTxId()可得到当前分布式事务的全局事务ID及本地事务ID,根据这个ID在去获取你补偿需要的参数,这可能需要业务系统做一些工作。
其实我是想表达,你们的readme里要补充一下,
这些方法参数需要是有无参构造器的类或基本类型。这是你们框架选择了kyro作为序列化库带来的潜规则了。
@gene1101 感谢提醒,kyro 序列化库的要求这块我们是需要在文档中进行标注。我这里建了一个JIRA SCB-1583来跟这个问题。
我这边有一个问题,就是Alpha端报 io.grpc.StatusRuntimeException: CANCELLED: call already cancelled, 这个异常是否和kyro反序列化失败相关。