Hmily 源码解析(一)

Hmily 源码解析(一)第一次看源码,也是第一次写分析源码的博文,写的不足之处希望多见谅。Hmily是分布式事务框架,基于TCC分布式事务概念。关于TCC概念我这边就不复述了,本博文基于对TCC概念有了解的基础上解析Hmily框架的实现。我计划将从两个维度进行分析,一个是业务流转的过程,通过状态的流转,方法调用来分析Hmily。另一个是从类功能的角度分析Hmily。主要以业务流转为主,类功能为辅解析Hmily的实…

大家好,又见面了,我是你们的朋友全栈君。


  • 第一次看源码,也是第一次写分析源码的博文,写的不足之处希望多见谅。
  • Hmily 是分布式事务框架,基于TCC分布式事务概念。关于TCC概念我这边就不复述了,本博文基于对TCC概念有了解的基础上解析Hmily框架的实现。
  • 我计划将从两个维度进行分析,一个是业务流转的过程,通过状态的流转,方法调用来分析Hmily。另一个是从类功能的角度分析Hmily。主要以业务流转为主,类功能为辅解析Hmily的实现,我觉得这样更能将hmily清晰的展现在我们眼前。

1.框架结构

  • 项目地址:https://github.com/yu199195/hmily
  • 解析基于的版本:2.0.3-RELEASE
  • 项目架构
    • hmily-admin:分布式事务后台模块,查看事务的失败情况等,这块暂不分析
    • hmily-dashboard:hmily-admin后台模块的前端页面,暂不分析
    • hmily-annotation:存放hmily的自定义注解
    • hmily-common: hmily核心模块,重点分析
    • hmily-core:hmily核心模块,重点分析
    • hmily-springcloud:基于springcloud分布式的hmily实现,重点分析
    • hmily-spring-boot-start:基于hmily-springcloud的再封装,暂不分析
    • 其它模块是基于dubbo等其他分布式框架的实现,同hmily-springcloud类似,我这边就分析基于springcloud的实现,毕竟其它的分布式框架我也没有接触过。
      在这里插入图片描述
  • hmily-demo模块
    • 基于springcloud分布式的demo
    • hmily-demo-springcloud-eureka:eureka注册中心
    • hmily-demo-springcloud-order:订单微服务
    • hmily-demo-springcloud-account:账户微服务
    • hmily-demo-springcloud-inventory:库存微服务
    • hmily-demo.sql:测试数据库初始化脚本
      在这里插入图片描述
  • 数据库结构
    • TCC 库: 事务日志库,为每一个微服务都建立一个日志表
    • order表:订单业务表
    • account表:账户金额表
    • inventory表:库存表

在这里插入图片描述

2.项目初始化

  • Hmily天然支持分布是的原因是因为Hmily本身就是基于分布式是实现的,它不像eureka之流有一个管理中心。Himly从代码层面的上来说没有主从之分。每一个需要使用或被参与到分布式事务的微服务都要依赖Hmily,它们之间的Hmily通信与状态的流转就是依靠于微服务本身的通信方式,比如springcloud中的fegin。
  • order,account,inventory都要参与分布事务,从业务上来说,order是主-发起者,其它两个是从-参与者。但是它们的初始化方式都是一样的,因为之前说了Himly在代码层面不存在主从分别,初始化我们通过一个微服务来讲解就好了。
    • 注:在看源码时我们会发现account的依赖方式同order,inventory不同。order、inventory是依赖hmily-springcloud,而account依赖与hmily-spring-boot-start。其实它们本质上是一样的,看hmily-spring-boot-start源码会发现它也是依赖于hmily-springcloud。它们的区别只是hmily-spring-boot-start可以把一些配置信息放置在application.yml文件中,hmily-springcloud是把信息放置在applicationContext.xml文件中。这里只是作者给我们提供了两种不同配置方案,我们根据项目需要选择就好。
  • 现在我们来分析hmily-demo-springcloud-order下Hmily的初始化。

在这里插入图片描述

  • 打开applicationContent.xml文件(截取核心的代码)
    在这里插入图片描述

  • HmilyTransactionBootstrap类处于core模块内。

    • 首先继承HmilyConfig类,这个类的作用是存放Hmily的配置信息,配置我都采用默认配置。
    • 另外又继承了ApplicationContextAware接口。这个接口只有一个抽象方法setApplicationContext,它的作用是在该对象实例化之后spring会调用该方法将ApplicationContext传递进来,我们看到ApplicationContext被放置到SpringBeanUtils的唯一实例之中,这样hmily就拥有了动态创建对象的能力。

在这里插入图片描述

  • 在对象初始化时,通过@Autowired注解spring实例了一个HmilyInitService对象进来,这个对象将继续进行着Hmily框架的初始化。
  • setApplicationContext方法在将ApplicationContext实例放置好之后,就以本实例为参数调用了start方法
  • 在start方法的参数类型是HmilyConfig,HmilyTransactionBootstrap的作用到这里已经结束了,只有它继承的HmilyConfig部分将继续发挥作用。start方法内只有一条语句,通过hmilyInitService将继续进行着Hmily框架的初始化。

  • HmilyInitService是接口,它的实现是HmilyInitServiceImpl类,我们定位到该类找到initialization方法
    在这里插入图片描述* 首先在虚拟机关闭时加了一个日志线程,输出关闭日志。
  • 其次根据配置文件加载spi支持
    • 一个是序列化方式, 默认是kryo序列化算法。一些类需要作为日志存储起来所以需要用到统一的序列化方式。
    • 一个是日志的维护接口(HmilyCoordinatorRepository),这里是采用db方式,具体实现类为JdbcCoordinatorRepository。维护的具体对象就是tcc库下的三张日志表。
    • 接着我们看到序列化方式被放置到HmilyCoordinatorRepository中了,看来对于对象的序列化只会在这里使用到。
    • 接着HmilyCoordinatorRepository实例根据HmilyCoordinatorRepository的class名被注册到SpringBeanUtils之中为单例对象。以后想要维护日志,根据HmilyCoordinatorRepository的class名从SpringBeanUtils中获取该实例即可。
      在这里插入图片描述
  • 我们继续看initialization方法,是hmilyCoordinatorService实例继续根据hmilyConfig接着初始化的工作。
  • hmilyCoordinatorService的来源呢?同上文一样在该实例初始化时被实例进来的。
    在这里插入图片描述
  • HmilyLogo().logo()的作用是初始化完成后输出banner日志,不多说了
  • 我们接着看hmilyCoordinatorService.start方法是如何初始化的

  • hmilyCoordinatorService接口的实现是HmilyCoordinatorServiceImpl类,它的是管理日志的service层,同前面的HmilyCoordinatorRepository实例配合使用。

  • 首先我们定位到start方法
    在这里插入图片描述

  • 首先是获取repositorySuffix,这个属性的作用是作为日志表的后缀名,比如tcc库下hmily_order_service表的后缀”order_service”,我们看一下是如何获取的。

  • buildRepositorySuffix方法内,首先hmilyConfig里面如果有配置,采用配置的(默认没有)。其次根据hmilyApplicationService(同上初始化时注入)获取,默认返回是application.yml文件中spring.application.name值。
    在这里插入图片描述

  • 我们看start方法的第二条语句,从SpringBeanUtils获取我们前面注册的coordinatorRepository对象并放置到hmilyApplicationService中。

  • 接着coordinatorRepository继续着初始化工作,已经第四个了。。。。


  • coordinatorRepository 是日志维护的Repository层,我们这边的实现类是JdbcCoordinatorRepository类,我们定位到init方法(尽力截图…)
    在这里插入图片描述
  • 第一步获取HmilyDbConfig,数据库的配置,我们在前面的配置文件中可以看到。
  • 接下来的if-else 是设置数据库连接的(dataSource),按下不表。
  • 接下来RepositoryPathUtils根据传进来的后缀属性生成日志表名,如例即得表名“hmily_order_service”
  • 接着DbTypeUtils根据配置文件获取连接的数据库类型,这里是mysql,作用先按下不表。
  • 最后生成日志, 首先通过SqlHelper生成创建表的sql语句,再通过executeUpdate执行该sql,都很简单不再细说了。

  • 到这边初始化就做完了,我们总结一下做了什么
  • 首先在SpringBeanUtils中我们有了ApplicationContext(应用上下文)了,拥有了创建实例对象与注册对象获取注册对象的功能。
  • 通过spi创建了ObjectSerializer(序列化方式),HmilyCoordinatorRepository(日志数据操作类),并把HmilyCoordinatorRepository注册到应用上下文之中为单例对象。把它注册进去为单例对象的原因是因为HmilyCoordinatorRepository中存储了和数据库的连接仓库(datasource),还有日志表名等。
  • 接着我们根据配置信息创建了日志表的表名,生成数据库连接信息datasource等都存储在HmilyCoordinatorRepository之中。最后创建了日志表。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143158.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • kworkers_kworker进程

    kworkers_kworker进程名字的意思什么时候有的这么看系统中查看显示的内容怎么看有什么用参考名字的意思KernelWorker什么时候有的kworker是3.x内核引入的这么看系统中查看Linux下使用ps-ef|grepkowrker显示的内容怎么看显示的格式kworker/%u:%d%su:是unbound的缩写,代表没有绑定特定的CPU,kworker/u2:0中的2是work_pool的

    2022年9月24日
  • .NET中代理服务器WebProxy的各种用法

    .NET中代理服务器WebProxy的各种用法因为涉及到代理的各种情况,WebRequest和WebProxy类的文档写的相当复杂,不但各个文档关注点不同,而且不同版本的同一文档也有小小的区别,网上也没有关于这个类的相关文章。于是乎这篇Blog是我钻研半天MSDN很久后总结并且花了一小时憋出来的,希望下面的内容能帮到大家。(AcDown中也使用了相关的代码,有兴趣的可以找来看看【解析】.NET中代理服务器WebProxy的各种用法)直接进入

    2022年6月21日
  • StringBuffer 详解 (String系列之3)[通俗易懂]

    StringBuffer 详解 (String系列之3)[通俗易懂]本章介绍StringBuffer以及它的API的详细使用方法。转载请注明出处:http://www.cnblogs.com/skywang12345/p/string03.htmlStringBuff

    2022年7月3日
  • 会员 数据库表设计[通俗易懂]

    会员 数据库表设计[通俗易懂]http://www.cnblogs.com/wuhuacong/p/3957428.html

    2022年6月20日
  • IntelliJ IDEA 快捷键整合(大全)

    IntelliJ IDEA 快捷键整合(大全)IntelliJIDEA快捷键整合大全1.代码标签输入完成后,按Tab,生成代码。2.查询快捷键3.其他快捷键4.svn快捷键5.调试快捷键6.重构7.其他1.代码标签输入完成后,按Tab,生成代码。Ctrl+Alt+O优化导入的类和包Alt+Insert生成代码(如get,set方法,构造函数等)或者右键(Generate)fori/sout/psvm+TabCtrl…

    2022年5月15日
  • c语言全局变量和局部变量的区别的代码_函数的形参都属于全局变量

    c语言全局变量和局部变量的区别的代码_函数的形参都属于全局变量局部变量和全局变量的区别背景:上午看书阅及这两对概念,有很多相似之处,故记之。一.局部变量&全局变量1局部变量:“在函数内定义的变量”,即在一个函数内部定义的变量,只在本函数范围内有效。2全局变量:“在函数外定义的变量”,即从定义变量的位置到本源文件结束都有效。目的:增加函数间数据联系的渠道。由于同一文件中的所有函数都能引用全局变量的值,因此如果在一个函数中改变了全局变…

    2022年10月24日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号