relates to #525
fescar hook是什么?
fescar hook的提供事务整个生命周期的入口,hook是thread级别,所以hook可以单独的使用在单个事务或多个事务,同理不同事务也可以注册不同的hook或同一hook,hook的生命周期随着单一事务的生命周期结束而结束。
fescar事务钩子需要保证fescar流程不中断,所以需要catch住hook的异常,现在有两个分歧点,当注册了多个钩子时,是否需要在fescar流程中catch每个hook的异常,还是作为整体catch hooks异常
All catch like

Every catch like

我认为是需要整体保证异常的catch
1.hook的使用是完全交给用户的,fescar是给用户提供了跟踪事务的业务入口,不需要规定用户的使用方式,只需要保证整体不影响事务流程即可。
2.整体catch的hook非常灵活,可以满足各种场景,针对每个hook都需要独立的场景也适用,用户只需要使用hook时,catch住异常,就和fescar catch每个hook异常是相同的效果
3.hooks的整体catch给了更多的扩展性,如优先级hook,链式hook可以根据实际需求场景由用户控制也可以后根据社区呼吁集成到fescar中
4.hook是线程级别的,控制hook的范围是和业务绑定的,不是全局的接口范围,所以需不需要抛出异常,hook链路是否有关联性,用户是非常清楚的,如果需要每个hook都需要catch住,那用户不用fescar做,作为一个考虑周全的程序员,他自己也会实际中那样做,

A事务则拥有的一个hook的生命周期,A事务结束,hook就会结束。
总结了issue里面对于全局catch的疑惑,我这里说明一下
1.hook与hook之间的设计就是没有任何关系的。hook之间没有任何互相依赖
2.对于单个事务注册的多个hook的hooks默认是有影响顺序的。
关于这两点我解释一下
对应hook是有全局事务注册和单个事务指定注册的使用场景,所以hook天生是需要扩展优先级概念的。
对于全局AHook事务有以下需求场景
A.Ahook不能被其它Hook影响,对于任何事务中的hooks,如果AHook执行失败,其余hooks不能执行,这样Ahook需要优先级靠前(与同为A场景hook判断优先级)且不能catch异常
B.Ahook不能被其它Hook影响,对于任何事务中的hooks,如果AHook执行失败,其余hooks能继续成功,这样Ahook需要优先级与A场景的hook设定优先级,且需要业务catch异常
C.Ahook能被其它Hook影响,对于任何事务中的hooks,如果AHook执行失败,其余hooks不能执行,根据ABC场景的hook比较优先级且不能catch异常
C.Ahook能被其它Hook影响,对于任何事务中的hooks,如果AHook执行失败,其余hooks能执行,则优先级一般是较靠后,且需要业务catch异常
综上所述,异常的catch由用户hook设定优先级,与是否需要对其它hook有影响来判断加入需要的异常处理,这块完全交给业务自由处理。
Hi @github-ygy, we detect non-English characters in the issue. This comment is an auto translation from @fescar-robot to help other users to understand this issue.
We encourage you to describe your issue in English which is more friendly to other users.
Is your feature request related to a problem? Please describe in details
The fescar transaction hook needs to ensure that the fescar process is not interrupted, so you need to catch the hook exception. Now there are two points of disagreement. When registering multiple hooks, do you need to catch each hook exception in the fescar process, or as a whole catch? Hooks exception
I think it is a catch that needs to guarantee an overall exception.
A clear and concise description of what you want to happen. You can explain more about input of the feature, and output of it.
Add any other context or screenshots about the feature request here.
i think we should catch Excetion inner the loop because:
class TransactionHook{
beforeBegin(){
for(YourBusinessTransactionHook hook in businessHooks){
hook.beforeBegin();
}
}
}
class YourBusinessTransactionHook{
}
this will help fescar keep simple, leave the extend logics to extend implements
relates to #525
Please comment on @github-ygy and @skyesx and vote for it, if you support @github-ygy please reply 1 and support @skyesx please reply 2.
请发表你们对 @github-ygy 和 @skyesx 关于对“tx hook should every catch or all catch” 观点的看法,并留下你们宝贵的一票,支持 @github-ygy 请回复1 ,支持 @skyesx 请回2.
1
1
Do you have any opinion on this issue? Allow discussion in Chinese
1
1
Do you have any opinion on this issue? Allow discussion in Chinese
从使用者的角度上,个人更愿意整体上获取异常,至于是哪一个hook发生的异常,交由相应的业务方关注即可。对于使用者而言,有更多的选择(All or One);重要的是有选择,而不是结果。其次异常日志方面也便于理解和排查;
其实问题本质的分歧是,Hook的实现是否可控
其实问题本质的分歧是,Hook的实现是否可控
扩展性?
还是没有特别理解这个hook,看大家的描述感觉作用像是aop一样在事务生命周期的某些节点执行用户自定义的业务逻辑吧,如果是这样,我觉得方案1比较好,整体catch已经可以保证事务主逻辑不会受到影响,异常应该是执行用户自定义业务逻辑时报的,所以这种情况下应该由用户自己处理异常,而不是fescar,如果理解有误的话,恳请各位大佬多多指点
还是没有特别理解这个hook,看大家的描述感觉作用像是aop一样在事务生命周期的某些节点执行用户自定义的业务逻辑吧,如果是这样,我觉得方案1比较好,整体catch已经可以保证事务主逻辑不会受到影响,异常应该是执行用户自定义业务逻辑时报的,所以这种情况下应该由用户自己处理异常,而不是fescar,如果理解有误的话,恳请各位大佬多多指点
和你的看法是一致的哈。
2
2
- 两种方式优先级和链式好像都可以支持,并不是只有全try起来才可以。
- 我觉得使用者并不想因为某个hook的失败而影响了所有的hook,可能这些hook并不是一个人维护的。新项目开始时约束的规定,如某个hook抛出异常将结束后面所有hook的运行,到项目后期维护的时候可能已经没有人能记住这样的规定了。可能某个新同学加了个无关紧要的hook但是抛出异常可能就影响了其它统计相关数据的异常,这是不应该的,我们不应该假设所有开发者的水平。
- 如果要开发者自己在每个hook方法都写上一个try catch的话,感觉代码极其不优雅。
hook可能不是同一个人维护的,但是hook不是全局的,是在单个事务生命周期的,这个时候对于hook的异常处理,在业务中应该是可以明确判断的。 hook的使用不是实现后就所有的事务都有了这个hook,必须手动的注册到指定的事务中,这块整体catch比较符合这个思路。我觉得出发点是fescar提供hook操作,但是不管hook的执行状态,我认为这个开发自己控制是比较好的。
另外补充两点
针对1,一般优先级和链式处理是相关联,异常的情况需要导致整个链路的断掉,这块整体catch提供是比较有好的
针对3 对于不需要影响业务代码主体流程的代码,业务中应该是视情况需要自定义catch住的,特别是有网络请求或超时请求,针对本地处理没有可能抛出未知异常的,如果有其他的代码bug出现的异常,我觉得fescar这边应该不需要提供这类情况的辅助catch
其实问题本质的分歧是,Hook的实现是否可控
扩展性?
这里应该不涉及扩展性,跟 @sofay 提的一样,优先级、跳出调用链 都可以在方案2上扩展实现
如果谈到是否可供用户选择,实际上方案2才是可选择的,方案1只能接受 其他不可控的Hook 抛出异常时,自己的Hook就不执行的情况,而方案1则没有这个限制
2
- 两种方式优先级和链式好像都可以支持,并不是只有全try起来才可以。
- 我觉得使用者并不想因为某个hook的失败而影响了所有的hook,可能这些hook并不是一个人维护的。新项目开始时约束的规定,如某个hook抛出异常将结束后面所有hook的运行,到项目后期维护的时候可能已经没有人能记住这样的规定了。可能某个新同学加了个无关紧要的hook但是抛出异常可能就影响了其它统计相关数据的异常,这是不应该的,我们不应该假设所有开发者的水平。
- 如果要开发者自己在每个hook方法都写上一个try catch的话,感觉代码极其不优雅。
hook可能不是同一个人维护的,但是hook不是全局的,是在单个事务生命周期的,这个时候对于hook的异常处理,在业务中应该是可以明确判断的。 hook的使用不是实现后就所有的事务都有了这个hook,必须手动的注册到指定的事务中,这块整体catch比较符合这个思路。我觉得出发点是fescar提供hook操作,但是不管hook的执行状态,我认为这个开发自己控制是比较好的。
另外补充两点
针对1,一般优先级和链式处理是相关联,异常的情况需要导致整个链路的断掉,这块整体catch提供是比较有好的
针对3 对于不需要影响业务代码主体流程的代码,业务中应该是视情况需要自定义catch住的,特别是有网络请求或超时请求,针对本地处理没有可能抛出未知异常的,如果有其他的代码bug出现的异常,我觉得fescar这边应该不需要提供这类情况的辅助catch
2
- 两种方式优先级和链式好像都可以支持,并不是只有全try起来才可以。
- 我觉得使用者并不想因为某个hook的失败而影响了所有的hook,可能这些hook并不是一个人维护的。新项目开始时约束的规定,如某个hook抛出异常将结束后面所有hook的运行,到项目后期维护的时候可能已经没有人能记住这样的规定了。可能某个新同学加了个无关紧要的hook但是抛出异常可能就影响了其它统计相关数据的异常,这是不应该的,我们不应该假设所有开发者的水平。
- 如果要开发者自己在每个hook方法都写上一个try catch的话,感觉代码极其不优雅。
hook可能不是同一个人维护的,但是hook不是全局的,是在单个事务生命周期的,这个时候对于hook的异常处理,在业务中应该是可以明确判断的。 hook的使用不是实现后就所有的事务都有了这个hook,必须手动的注册到指定的事务中,这块整体catch比较符合这个思路。我觉得出发点是fescar提供hook操作,但是不管hook的执行状态,我认为这个开发自己控制是比较好的。
另外补充两点
针对1,一般优先级和链式处理是相关联,异常的情况需要导致整个链路的断掉,这块整体catch提供是比较有好的
针对3 对于不需要影响业务代码主体流程的代码,业务中应该是视情况需要自定义catch住的,特别是有网络请求或超时请求,针对本地处理没有可能抛出未知异常的,如果有其他的代码bug出现的异常,我觉得fescar这边应该不需要提供这类情况的辅助catch
- 即使是线程相关,非全局的,你也不知道有谁会在什么位置加什么东西,例如Spring MVC里有很多filter,我们能很轻松地说出 不同地组件往里面塞了什么filter么?因此 “这个时候对于hook的异常处理,在业务中应该是可以明确判断的” 个人感觉是不成立的
- 同时方案2能实现的功能并非方案1的子集,而是超集,只是你需要自行扩展一些接口而已
filter的设计是不会单一catch的,应该是根绝filter的重要性,在实现内部进行catch,我去瞅瞅springmvc的filter
我们要提供的是扩展性,而非帮用户设计逻辑,只要用户能优雅扩展,问题就已经解决了。
而方案1,从跳出调用链需要依赖于fescar实现的细节来说,业务已经跟框架产生了更强的耦合
我们要提供的是扩展性,而非帮用户设计逻辑,只要用户能优雅扩展,问题就已经解决了。
而方案1,从跳出调用链需要依赖于fescar实现的细节来说,业务已经跟框架产生了更强的耦合另外我补充一点,hook是针对具体事务的生命周期结束而结束的,这本来就是为tx生命周期服务,所以设计的时候也是Thread级别的。这不存在耦合问题。同一个事务方法,在不同的线程中,就是两个事务,就可以注册不同类型的hook,hook的选择,hook的使用都是完全自由的。
我们要提供的是扩展性,而非帮用户设计逻辑,只要用户能优雅扩展,问题就已经解决了。
而方案1,从跳出调用链需要依赖于fescar实现的细节来说,业务已经跟框架产生了更强的耦合另外我补充一点,hook是针对具体事务的生命周期结束而结束的,这本来就是为tx生命周期服务,所以设计的时候也是Thread级别的。这不存在耦合问题。
跳出 业务自行设定的一系列内容相关的调用链(如果是无关,互相独立的hook,为什么其他hook的实现会影响到我的hook执行或者不执行?) 依赖于fescar triggerBegin()方法的具体实现,而非自行控制,个人觉得是耦合,但你觉得不是,那你有你自己看法的权力
至于Thread级别的tx生命周期这件事,虽然可能看起来粒度小,但他可以很大,因为只要你提供了扩展接口出去,你是没办法想像别人能做什么扩展。你可以控制自己hook什么进去,但你没办法控制别人hook什么进去
再回到你的观点,你认为大家hook都肯定是可靠的,遵循规范的,那规范有什么办法可以确保每个人都执行呢?即使有的话,我框架就限定了你不影响别人又有什么坏处呢?
1.方案赞同吧
对于thread 级别的hook , 而且是tx , 这个设计之初就是一个整体。
对于异常,没必要每个都加,有异常业务感知自己去搞
hook可能不是同一个人维护的,但是hook不是全局的,是在单个事务生命周期的,这个时候对于hook的异常处理,在业务中应该是可以明确判断的。 hook的使用不是实现后就所有的事务都有了这个hook,必须手动的注册到指定的事务中,这块整体catch比较符合这个思路。我觉得出发点是fescar提供hook操作,但是不管hook的执行状态,我认为这个开发自己控制是比较好的。
另外补充两点
针对1,一般优先级和链式处理是相关联,异常的情况需要导致整个链路的断掉,这块整体catch提供是比较有好的
针对3 对于不需要影响业务代码主体流程的代码,业务中应该是视情况需要自定义catch住的,特别是有网络请求或超时请求,针对本地处理没有可能抛出未知异常的,如果有其他的代码bug出现的异常,我觉得fescar这边应该不需要提供这类情况的辅助catch
hook是不是全局的话对于这个问题来说感觉影响不是太大,单个生命周期内,也可以被不同的人加不同的hook,如果自己封装之后可能不同的人在不同的地方加了不同的Hook T_T,我是觉得单个处理的话对使用者的包容性更大一点,容错也更大。 尽可能不让一个无关的去影响了所有的。如果开发都想要某个hook抛异常然后停止其它的话,也可以使用一个共享的变量或者借助一个中间类来控制。
感觉链路断不断和目前这个问题是一样问题,链路也可以处理成不断,就看目前这个的讨论结果了。
必要的try catch肯定是重要的。但是如果每个hook没有父类没有使用模板的话,每次新建一个hook 都是
class XxxHook {
void execute(){
try{
....
} catch (Exception) {
}
}
}
这个样子的话,代码看起来不是那么优雅。
当然每个写法有每个写法的好处,看出发点和考虑在哪了。
2
不知道我理解的对不对,这个接口提供给用户在事务开始执行时提供前置和后置的实现接口。现在是讨论前置和后置接口在处理异常的时候是整个前置/后置链catch异常是在循环内还是循环外。我个人感觉应该是在循环内,这样一个hook失败不会导致所有的hook链都失败。
2
2
不知道我理解的对不对,这个接口提供给用户在事务开始执行时提供前置和后置的实现接口。现在是讨论前置和后置接口在处理异常的时候是整个前置/后置链catch异常是在循环内还是循环外。我个人感觉应该是在循环内,这样一个hook失败不会导致所有的hook链都失败。
你的理解是对的,但是我想做一个说明
这里的hooks是针对单个事物维度的,不是全局的,所以每个事物可以有不同的hooks集合,我们把hooks集合看成一个整体hook给用户使用,不是一个接口实现了多个hook那么每个事物都拥有了所有的hooks,hook的使用肯定是用户指定使用的,那么把thread级别的多个hook的选择肯定是趋向于有关联性的,这是应该由业务来决定而不是fescar来决定
hook可能不是同一个人维护的,但是hook不是全局的,是在单个事务生命周期的,这个时候对于hook的异常处理,在业务中应该是可以明确判断的。 hook的使用不是实现后就所有的事务都有了这个hook,必须手动的注册到指定的事务中,这块整体catch比较符合这个思路。我觉得出发点是fescar提供hook操作,但是不管hook的执行状态,我认为这个开发自己控制是比较好的。
另外补充两点
针对1,一般优先级和链式处理是相关联,异常的情况需要导致整个链路的断掉,这块整体catch提供是比较有好的
针对3 对于不需要影响业务代码主体流程的代码,业务中应该是视情况需要自定义catch住的,特别是有网络请求或超时请求,针对本地处理没有可能抛出未知异常的,如果有其他的代码bug出现的异常,我觉得fescar这边应该不需要提供这类情况的辅助catchhook是不是全局的话对于这个问题来说感觉影响不是太大,单个生命周期内,也可以被不同的人加不同的hook,如果自己封装之后可能不同的人在不同的地方加了不同的Hook T_T,我是觉得单个处理的话对使用者的包容性更大一点,容错也更大。 尽可能不让一个无关的去影响了所有的。如果开发都想要某个hook抛异常然后停止其它的话,也可以使用一个共享的变量或者借助一个中间类来控制。
感觉链路断不断和目前这个问题是一样问题,链路也可以处理成不断,就看目前这个的讨论结果了。
必要的try catch肯定是重要的。但是如果每个hook没有父类没有使用模板的话,每次新建一个hook 都是class XxxHook { void execute(){ try{ .... } catch (Exception) { } } }这个样子的话,代码看起来不是那么优雅。
当然每个写法有每个写法的好处,看出发点和考虑在哪了。
关于hook的理解,我也一些不同的看法,hook失败不会导致所有的hook链失败,如果用户单个事务的hook有优先级的概念,那是否要自己额外维护一套自己的localhooks放入到单个 fescar hook中? fescar的hook设定是thread级别的,而且是随着单个事务的生命周期的,针对单个事务的hooks,可以看做一个整体,具体的操作是交给业务处理的,其实如果单个事务注册了多个hooks,大概率都是有关联性的。
关于代码的优雅这点,我说明一下,平常的业务代码我们是否每个提交的代码都进行了catch? 这肯定不是的,如果针对没有额外的网络操作和可预见的失败的操作,这类型是不必要加catch'的,如果有其他的空指针异常,这块应该有用户来承担bug问题,因为hooks这块的维度是针对单个事务的,不是全局的所有方法事务,单个事务所需要的hook是哪种类型,这块业务是有感知的,可选安全型的hook,或者执行链路的hook都能自由选择
https://github.com/alibaba/fescar/issues/557#issuecomment-470879981
我后来去看了下spring,createBean方法里面beanProcess接口的实现处理也是方在整个链的外面的。
2
我觉着在内部catch比较好。两种方案从实现角度看,都可以实现中断循环以及hook之间互不影响,但我觉着如果是从用户的角度来看,应该不会希望hook之间互相影响,所以在hook里面catch可能对用户体验感觉会稍差一些;如果有需要中断后续hook的执行 (2号选手好像说明了可以中断的方案,我没太理解,这个说的是我个人的一个解决方案) 则可以规定一个特定的异常类交由hook去throw,类似如下代码
for(){
try {
****
} catch (***Exception e){
throw new ****Exception;
} catch(Exception e) {
Log.error(****);
}
}
2
我觉着在内部catch比较好。两种方案从实现角度看,都可以实现中断循环以及hook之间互不影响,但我觉着如果是从用户的角度来看,应该不会希望hook之间互相影响,所以在hook里面catch可能对用户体验感觉会稍差一些;如果有需要中断后续hook的执行 (2号选手好像说明了可以中断的方案,我没太理解,这个说的是我个人的一个解决方案) 则可以规定一个特定的异常类交由hook去throw,类似如下代码
for(){ try { **** } catch (***Exception e){ throw new ****Exception; } catch(Exception e) { Log.error(****); } }
hook之间的设计就是互相不影响的,这块的hooks是针对单个事务级别的,是手动给一个事务添加多个hook对象,那么这个事务绑定了多个hook是否有影响,不应该由fescar来判断,由用户自己决定。
另外我再补充一点给大家, hook之前本来就是相互没影响的,给事务添加hooks是给具体事务添加hook不是全局的,那么这块的hooks应该看成是单个事物的整体hook,具体的子hook需要如何关联,用户业务决定。
2
我觉着在内部catch比较好。两种方案从实现角度看,都可以实现中断循环以及hook之间互不影响,但我觉着如果是从用户的角度来看,应该不会希望hook之间互相影响,所以在hook里面catch可能对用户体验感觉会稍差一些;如果有需要中断后续hook的执行 (2号选手好像说明了可以中断的方案,我没太理解,这个说的是我个人的一个解决方案) 则可以规定一个特定的异常类交由hook去throw,类似如下代码
for(){ try { **** } catch (***Exception e){ throw new ****Exception; } catch(Exception e) { Log.error(****); } }hook之间的设计就是互相不影响的,这块的hooks是针对单个事务级别的,是手动给一个事务添加多个hook对象,那么这个事务绑定了多个hook是否有影响,不应该由fescar来判断,由用户自己决定。
另外我再补充一点给大家, hook之前本来就是相互没影响的,给事务添加hooks是给具体事务添加hook不是全局的,那么这块的hooks应该看成是单个事物的整体hook,具体的子hook需要如何关联,用户业务决定。
对于单个事务的多个hook之间是否有影响这个是不应该由fescar来判断,应该由用户自己决定;但是fescar怎样都要有一个默认的实现,也就是fescar的一个规格,这个规格本身对fescar的影响其实是不重要的,那就应该以用户的方便去实现;既然hook之间的设计就是互不影响的,那这个就没有必要去暴露给用户去做catch,如果用户有中断需求,那他只需要throw个规定好的异常出来即可;如果是外部catch的话其实对用户来看是属于多个hook之间会互相影响的设计了,应该是就跟最初的设计是不符的了吧
如果hook是链式处理,任何一个环节出问题 是不是都不影响下一个链,每一个hook只需要catch住runtimeexception异常
我选择方案1, 对于有些觉得某个hook的执行失败会导致其他的hook都不执行这一情况, 其实可以尝试记录循环到哪个hook,然后跳过继续执行后面的来确保所有hook的执行
I prefer to option 2 as well.
In my view, the reasons for option 2 are:
1). There is a scene when interrupted that we can know which hook is interrupted. We needn't to add some state to keep it.
2). We shouldn't assume that every development have such professional skills.
我选择方案2,如果 hook 在单个事务中不相互影响的话,我觉得 2 方案比较好。不能开那么大的口子让开发人员影响到之前的 hook.
我支持2.
从技术上来讲我觉得区别不大?从可维护性上来讲,2要比1要好一点。
1
我觉得是不应该干预业务的,
如果hook彼此是无关的,整体和内部异常是一样的;
如果hook彼此是有关的,则应由用户保证业务一致性,抛不抛异常,由用户决定。
2的设计理念更直观。hook之间默认不应该有关系,而是在需要有关系的时候有相应的中断机制。这样使用起来才不容易踩坑
2
扩展性更强一点,提供1为默认实现,我觉得这样是最好的
Most helpful comment
2