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

同库短路设计 #23

Open
abelfine opened this issue Apr 21, 2018 · 12 comments
Open

同库短路设计 #23

abelfine opened this issue Apr 21, 2018 · 12 comments
Milestone

Comments

@abelfine
Copy link

你好,最近把EasyTransaction的源码仔细看了一遍,感觉框架写的很棒。接口设计清晰,能够把编码的复杂度分离到各个模块中(各种不同的listener来处理消息),看了之后很有启发。
看了问题列表中同库短路设计还未开始,想问一下同库短路是什么意思,应用业务场景是啥?我对这个问题蛮有兴趣的,期待能够有幸参与开发。

@skyesx
Copy link
Contributor

skyesx commented Apr 22, 2018

同库短路是指当 最终一致的 主事务 跟 从事务 都在同一个服务,可以合并成同一个单库事务,主要用于优化性能,不用走RPC分两个事务完成。

同库短路在我的设想里,以TCC为例,如果发起方跟TCC服务提供方是同一个服务,那么可以直接在同一个事务里执行完TRY和CONFIRM的操作,这样能提高效率。这是同库短路的一种提供优化的形式。

另外一种,如果有客户有进一步优化性能的需求,可以提供一个TRY和CONFIRM的合并优化的方法(即无需调用CONFIRM,TRY里已经把CONFIRM做了)

不知道我有没有说清楚,期待你的参与

@abelfine
Copy link
Author

基本上理解了。这个 就像dubbo服务的本地暴露相似,如果消费端发现要消费的服务本地存在,就不用走rpc分支,直接进行本地调用了。

@abelfine
Copy link
Author

还要花时间研究一下,easytrans的源码。

@moonboat
Copy link

moonboat commented May 3, 2018

这个是个很棒的议题。
首先:
需要对业务有记录,就是类型,同一个业务app, 注册的时候,接口或者标签。解析(注册)的时候,就已经知道什么类型了, 一个app肯定是在自己的内存中注册(注册中心集中管理另说)。
事务调用:
目前是program手动调用,类似spring filter chain, 肯定可以改成aop,隐式调用,并且本身已经嵌入到spring 的transaction中,研究下spring的transaction调用链,应该可以注册自己的filter进去,或者扩展spring的transaction的handler进去。 就可以实现透明调用。

有了透明调用,又有了业务注册类型,那么就不需要手动代码调用,自然就达到了同库短路设计。根据业务类型框架判断走remote还是直接跳过(执行本地事务)。

个人理解,不对的地方一起讨论,学习下

@skyesx
Copy link
Contributor

skyesx commented May 3, 2018

关键有几个问题:

  • 如何识别能否短路?根据APP名自行判断?交给业务自行判断?
  • 如何找到短路时,原本在远程执行的代码块(TCC如何找,消息触发的操作如何找)
  • 对于不同类型的事务形态,如何合并不同阶段的代码块(如TCC中,找到Try和Confirm的代码并在同一线程内同步调用)

@moonboat
Copy link

moonboat commented May 3, 2018

  • 如何识别能否短路?根据APP名自行判断?交给业务自行判断?

    按照现在设计,实现接口的类, 启动时进过扫描,封装到map, 这些类就是自身的app,spring.application.name 取这个类型最简单。

  • 如何找到短路时,原本在远程执行的代码块(TCC如何找,消息触发的操作如何找)

    dubbo是有同库短路的。具体没研究过实现,只是使用经验。待研究代码确认?
    初步想法:
    app A1, A2.

    1. 发起方app A1中的 A业务。
      A调用A1中的B,A2的C
      B为本本地,执行到的时候(运行中),判断角色,直接跳过,参与本地事务,调用的时候,自然就是
      同一线程,比如feigin,rpc,就不发起远程执行方法,而直接找本地的impl直接运行(这个肯定不是问题,可以实现)。
      执行到C的时候,为A2的app,判断角色后,按照远程调用执行现在已有的分布式事务机制。
  • 对于不同类型的事务形态,如何合并不同阶段的代码块(如TCC中,找到Try和Confirm的代码并在同一线程内同步调用)

    这个第二个问题中已经说到了。

@moonboat
Copy link

moonboat commented May 3, 2018

第三个TCC可能没说清楚,因为TCC有3个方法, 在执行B,假如为A1的TCC, 已经知道这个属于A1,是本地角色,后面的调用,都反射本地的impl的class执行(缓存)。

@skyesx
Copy link
Contributor

skyesx commented May 3, 2018

恩,大思路都差不多,就看如何具体整合代码到现有框架了

@moonboat
Copy link

moonboat commented May 3, 2018

期待1.0.1支持

@abelfine
Copy link
Author

abelfine commented May 5, 2018

看了一下源码,原本打算添加一个EasyTransExecutorFilter之类的过滤器来执行短路逻辑判断,如果不短路的话,就记录执行日志,调用rpc服务。否则直接调用本地服务。但是通过消息来完成rpc调用的话,就不太好进行判断了。
个人感觉,因为我们这个框架是基于某些rpc框架的,如果这些rpc框架不支持短路的话,那么easytrans支持起来会比较困难吧。(我这个理解的有没有问题?)
ps:RemoteServiceCaller这个类 写的有点小瑕疵,可以把EasyTransRpcConsumer 和EasyTransMsgPublisher 分开,通过 adapter 适配一下,上层 调用 方式 会更加统一

@skyesx
Copy link
Contributor

skyesx commented May 6, 2018

先确定一下我的理解是否正确,

这里 “通过消息来完成RPC调用”,指代的是通过消息队列发送异步消息,业务主流程上不等待对方回应的的调用

基于上述的理解,我觉得这里可以分两块来看:

  • 同步的RPC调用(一对一,DUBBO/REST/FEIGN等),这个的做法就跟你上面写的一样,判断下是否短路,要短路则跳过日志,直接本地执行
  • 异步的RPC调用(一对多,基于消息队列等,不要求拿返回结果的),这个我觉得可以不短路,因为实际上,发布消息出去可能有多个接收者,并且它并非是业务执行的关键路径,短路反而可能降低主流程性能,所以这个倒是可以不做

对于RemoteServiceCaller这个没确切看懂啥意思,是否指代希望 RemoteServiceCaller 不区分 publish和call两个方法的调用形式?但是实际上外部调用者是需要区分这两个的,因为发布消息会有个消息ID等额外的元信息,所以是不能合并的

如果不是的话,能不能直接单独提一个PR,代码应该不多,看代码比较具体,更容易看出意图

@abelfine
Copy link
Author

abelfine commented May 8, 2018

我改下试试

@skyesx skyesx added this to the 1.4.x milestone Jun 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants