Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature : SAGA annotation mode #4577

Closed
wants to merge 45 commits into from
Closed

feature : SAGA annotation mode #4577

wants to merge 45 commits into from

Conversation

sunrui1225
Copy link
Contributor

@sunrui1225 sunrui1225 commented Apr 30, 2022

Ⅰ. Describe what this PR did

The PR add SAGA annotation mode to seata. The current SAGA mode solution is based on state machine which is difficult to learn and operated. It's easy for the short tranction with SAGA annotation mode.

20230204 Closed. Please see pr #5300

Ⅱ. Does this pull request fix one issue?

fixes #4571

Ⅲ. Why don't you add test cases (unit test/integration test)?

Ⅳ. Describe how to verify it

Ⅴ. Special notes for reviews

@sunrui1225 sunrui1225 marked this pull request as draft April 30, 2022 10:36
@sunrui1225 sunrui1225 marked this pull request as ready for review April 30, 2022 10:37

// if the TwoPhaseBusinessAction annotation's mode is SAGA, cancel the commit
ModeType modeType = (ModeType) businessActionContext.getActionContext(Constants.MODE_TYPE);
if(modeType != null && modeType.equals( ModeType.SAGA)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码格式化一下

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果spring cloud用户使用注解式SAGA的话,需要打上@LocalTCC的注解,对于用户来说这个其实比较困惑

Copy link
Contributor Author

@sunrui1225 sunrui1225 May 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

您好,已经格式提交。
确实@LocalTCC会让用户迷惑,所以我定义了一个新的注解Compensable和 LocalSAGA 与TCC区分,请见#4577 (comment)
此注解也定义了向前重试机制

@tanzzj
Copy link
Contributor

tanzzj commented Apr 30, 2022

对于SEATA来说,要不要再多走一步,即SEATA自动向前做重试补偿

@funky-eyes
Copy link
Contributor

对于SEATA来说,要不要再多走一步,即SEATA自动向前做重试补偿

如果是1.5.x版本的觉得当前的pr做法是可以接受的,如果是2.x版本我觉得应该步子迈大

Copy link
Contributor

@funky-eyes funky-eyes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

另外ActionInterceptorHandler#doTccActionLogStore 中应该传递branchtype注册至tc,否则到tc还是认为是tcc分支

@@ -97,6 +98,14 @@ public BranchStatus branchCommit(BranchType branchType, String xid, long branchI
//BusinessActionContext
BusinessActionContext businessActionContext = getBusinessActionContext(xid, branchId, resourceId,
applicationData);

// if the TwoPhaseBusinessAction annotation's mode is SAGA, cancel the commit
ModeType modeType = (ModeType) businessActionContext.getActionContext(Constants.MODE_TYPE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DefaultCore#doGlobalCommit 直接处理即可

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我再看一下这里DefaultCore#doGlobalCommit ,如果结合新的注解Compensable来处理

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

另外ActionInterceptorHandler#doTccActionLogStore 中应该传递branchtype注册至tc,否则到tc还是认为是tcc分支

确实要改成SAGA的branchtype,所以对于ActionInterceptorHandler来处理SAGA,我想可能新增一个doSagaActionLogStore来处理,或者考虑可重用来在内部兼容处理SAGA的branchtype注册至tc

*
* @author ruishan
*/
public enum ModeType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不要使用新类,直接使用BranchType 枚举类

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已经去掉ModeType,改成BranchType

@funky-eyes funky-eyes added type: feature Category issues or prs related to feature request. mode: SAGA SAGA transaction mode labels May 1, 2022
@funky-eyes
Copy link
Contributor

另外应该独立一个TwoPhaseBusinessAction给saga使用因为某些参数是不适用于saga的,如commitMethod,此外第一版可以将spring module和seata-tcc稍微改一下依赖关系,seata-tcc应该依赖spring module而不是springmodule依赖seata-tcc,可以先把相关注解挪到spring module去

@sunrui1225
Copy link
Contributor Author

另外应该独立一个TwoPhaseBusinessAction给saga使用因为某些参数是不适用于saga的,如commitMethod,此外第一版可以将spring module和seata-tcc稍微改一下依赖关系,seata-tcc应该依赖spring module而不是springmodule依赖seata-tcc,可以先把相关注解挪到spring module去

您好,确实TCC和SAGA的注解是不适用的,所以我想为SAGA设计一个新的注解Compensable,注解的属性如下:
compensationMethod 补偿方法
forwardRetries 向前失败重试次数
reverseRetries 补偿失败重试次数
retryDelayInMilliseconds 重试间隔时间

以上注解属性定义了SAGA的向后补偿方法,以及向前重试次数机制等。

但是我在修改的代码的时候,感觉要改动的地方好像有些多,有些不太确定是应该新增还是,在原方法修改,我总结了我的一些修改点:
● io.seata.spring.util.TCCBeanParserUtils#isTccAutoProxy
新增加isSAGAAutoProxy

● 在tcc/src/main/java/io/seata/rm/tcc/remoting/parser下增加一个 SAGARemotingParser 分析器,主要是分析一下是否接口被LocalSAGA注解,是的话说明则

● io.seata.rm.tcc.remoting.parser.DefaultRemotingParser#parserRemotingServiceInfo
要修改,增加SAGA的分支注册,把SAGA注解中的属性如补偿方法等保存在cache中,以便在拦截器中用。

● 新增加拦截器
SAGAActionInterceptor 对应于 TccActionInterceptor
实现io.seata.spring.tcc.TccActionInterceptor#invoke方法,主要是注入xid,

● 拦截处理器,是否也要新增
io.seata.rm.tcc.interceptor.ActionInterceptorHandler#proceed
在这里会,上报tc,要把TCC改成SAGA
io.seata.rm.tcc.interceptor.ActionInterceptorHandler#doTccActionLogStore
请帮忙看一下这样是否可行?

还有一个问题就是我没有太准确的理解 seata-tcc如何得去依赖spring module。因为在原有依赖上,我看是在seata-spring中的io.seata.spring.annotation.GlobalTransactionScanner#wrapIfNecessary 去调用TCC包中分析器,以及上报TC都是在TCC包中的拦截器做的,能帮再指明一下吗?

@sunrui1225
Copy link
Contributor Author

另外ActionInterceptorHandler#doTccActionLogStore 中应该传递branchtype注册至tc,否则到tc还是认为是tcc分支

确实要改成SAGA的branchtype,所以对于ActionInterceptorHandler来处理SAGA,我想可能新增一个doSagaActionLogStore来处理,或者考虑可重用来在内部兼容处理SAGA的branchtype注册至tc

@funky-eyes
Copy link
Contributor

@sunrui1225
1.Compensable应该改为SagaTransactional
2.向前重试暂时可以先不搞,如果是从rm端重试那倒是可以加,就像rpc重试一样的意思
3.补偿失败暂时也不用搞,这个弄起来麻烦,这个直接跟tcc一样tc端控制来驱动回滚即可
4.据我感觉分析器是否可以跟tcc放在一起,if else判断下就行了吧?
5.localsaga如上同理
6.拦截器暂时也可以用tcc的,后面咱们再完善也不迟
7.处理器就直接用tcc的就行了,你识别到有saga这个注解不就是saga模式了吗,把type改成saga即可,tc端DefaultCore#doGlobalCommit 直接判断如果是saga分支,直接可以删掉这个分支了因为一阶段已经提交了

@sunrui1225
Copy link
Contributor Author

sunrui1225 commented May 14, 2022

@sunrui1225 1.Compensable应该改为SagaTransactional 2.向前重试暂时可以先不搞,如果是从rm端重试那倒是可以加,就像rpc重试一样的意思 3.补偿失败暂时也不用搞,这个弄起来麻烦,这个直接跟tcc一样tc端控制来驱动回滚即可 4.据我感觉分析器是否可以跟tcc放在一起,if else判断下就行了吧? 5.localsaga如上同理 6.拦截器暂时也可以用tcc的,后面咱们再完善也不迟 7.处理器就直接用tcc的就行了,你识别到有saga这个注解不就是saga模式了吗,把type改成saga即可,tc端DefaultCore#doGlobalCommit 直接判断如果是saga分支,直接可以删掉这个分支了因为一阶段已经提交了

seata-spirng 与 seata-tcc的依赖关系问题
目前seata-spring中有一些强依赖seata-tcc的服务方法,如是否是tcc模式的判断,tcc拦截器。造成拓展性比较差。
想把这些强依赖的文件迁移到seata-spring中,seata-tcc对seata-spring不可见。tcc和saga包只放独有的注解。再seata-spring以SPI的形式做tcc和saga的拓展。把分析器中对模式判断做抽象,以SPI做tcc和saga的拓展。
拦截器也是做抽象,以SPI对tcc和saga的拓展。
分两次pr,一是迁移强以来的文件到spring中。二是把模式判断和拦截器均做抽象,SPI拓展。

pr1(迁移)

  1. seata-tcc中只保留@LocalTCC,@TwoPhaseBusinessAction,剩下的文件都迁移到seata-spring中。
  2. 对用户暴露的有两个文件迁移后不能改变路径,分别是io.seata.rm.tcc.api.BusinessActionContext 和 注解io.seata.rm.tcc.api.BusinessActionContextParameter,在spring中是否可以可以建立一个空类BusinessActionContext,路径是之前的路径,继承新路径下的类。
  3. 其他迁移的文件包括解析器,拦截器,TCCFence均迁移至seata-spring中。

pr2(加入SAGA模式,抽象拓展)

  1. 在扫描器io.seata.spring.annotation.GlobalTransactionScanner#wrapIfNecessary中,把下图片中分析器和拦截器均做抽象。
  2. 把现有TCC模式下可以公用的部分都移出来到扫描器的主类中,并把TCC相关的部分做抽象的子类,利用SPI做拓展,通过tcc包下的tcc注解识别。
  3. 加入SAGA模式,实现分析器和拦截器的抽象子类。
  4. 在seata-spring中建立新注解@Localservice,代表dubbo本地化。
  5. 建立saga包,创建saga注解为SagaTransactional。

image

@@ -134,4 +136,43 @@ public static void setContext(BusinessActionContext context) {
public static void clear() {
CONTEXT_HOLDER.remove();
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 111, branchReport(BranchType.TCC, 这里需要区分下tcc saga,类型从参数获取

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改

if (sagaResource == null) {
throw new ShouldNeverHappenException(String.format("Saga resource is not exist, resourceId: %s", resourceId));
}
if (sagaResource.isUseSagaAnnotationMode()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saga一阶段里面开启防悬挂后,会插入悬挂表记录,二阶段如果不更新防悬挂表,悬挂记录就无法清理了,这里检查下,需要更新防悬挂记录状态。
记录清理任务入口:io.seata.spring.fence.TCCFenceHandler#deleteFenceByDate()
清理状态:status in (" + TCCFenceConstant.STATUS_COMMITTED + " , " + TCCFenceConstant.STATUS_ROLLBACKED + " , " + TCCFenceConstant.STATUS_SUSPENDED + ")"

import io.seata.rm.tcc.store.db.TCCFenceStoreDataBaseDAO;
import io.seata.spring.fence.TCCFenceHandler;
import io.seata.spring.fence.exception.TCCFenceException;
import io.seata.spring.fence.store.db.TCCFenceStoreDataBaseDAO;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TCCFence是属于通用类型,tcc和saga可以通用,也不数据用户接触api,考虑改名

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改,检查了下通用防悬挂的名字,也做了修改

* @return the branchId
*/
protected String doTccActionLogStore(Method method, Object[] arguments, TwoPhaseBusinessAction businessAction,
protected String doTccActionLogStore(Method method, Object[] arguments, TwoPhaseBusinessActionParam businessActionParam,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

方法改名,其他地方也可以检查下

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改,检查了下通用防悬挂的名字,也做了修改

Method[] methods = sagaInterfaceClazz.getMethods();
for (Method method : methods) {
SagaTransactional sagaTransactional = method.getAnnotation(SagaTransactional.class);
if (sagaTransactional != null && (Protocols.IN_JVM == remotingDesc.getProtocol() || remotingDesc.isReference())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IN_JVM 也可以通过 remotingDesc.isReference()判断

@leezongjie
Copy link
Contributor

saga失败触发全局回滚事件时,GlobalRollbackRequest,server接收到后判断了如果是saga就将回滚发送给发起者做状态机向前重试或者回退。saga注解这里需要额外注意,目前没有向前重试,发起者又没有对分支做存储,所以可能需要判断下如果是注解,就需要按照tcc部分,给每个分支rm发送分支回滚BranchRollbackRequest。

image

image

@sunrui1225
Copy link
Contributor Author

saga失败触发全局回滚事件时,GlobalRollbackRequest,server接收到后判断了如果是saga就将回滚发送给发起者做状态机向前重试或者回退。saga注解这里需要额外注意,目前没有向前重试,发起者又没有对分支做存储,所以可能需要判断下如果是注解,就需要按照tcc部分,给每个分支rm发送分支回滚BranchRollbackRequest。

image

image

已经修改,新增了saga注解的resource manager,和saga注解机完全独立开

@CLAassistant
Copy link

CLAassistant commented Dec 12, 2022

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ sunrui1225
❌ ruishansun


ruishansun seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
0 out of 2 committers have signed the CLA.

❌ ruishansun
❌ sunrui1225


ruishansun seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@sunrui1225 sunrui1225 closed this Feb 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mode: SAGA SAGA transaction mode type: feature Category issues or prs related to feature request.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

增加 saga注解模式
6 participants