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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java中 +=和+的区别[通俗易懂]

    java中 +=和+的区别[通俗易懂]java中+=的意义包含两部分,一是"+",就是通常所说的直接相加,二是改变结果的类型,将计算结果的类型转换为"+=符号左边的类型。比如:shrots=1;s+=1这个语句其实就是s=(short)(s+1)…

    2022年7月8日
    17
  • nginx如何处理TIMEWAIT过多?

    nginx如何处理TIMEWAIT过多?在高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常连接。这个场景下会出现大量socket处于TIME_WAIT状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。首先先查看tcp连接状态及数量:#netstat-n|awk‘/^tcp/{++S[$NF]}END{for(ainS)printa,S[a]}’或者#netstat-ant|awk’/^tcp/{++S[$NF]}END{for(ainS)print(a,S[a])}

    2022年5月2日
    146
  • sg90舵机工作原理_舵机跑舵?锲而不舍终除隐患![通俗易懂]

    sg90舵机工作原理_舵机跑舵?锲而不舍终除隐患![通俗易懂]因为专注才更专业,快快关注吧!欢迎投稿:sea@shipmg.com正文开始一、前言某司二条姐妹船采用SSP5型360º全回转电力推进器,左右两台中压永磁电机推进船舶行驶,另外两面分别由两台P14S金杯油泵驱动三台CA210型赫格隆内曲线液压油马达360º控制船舶回转方向。在机动航行时使用港口模式,推进器可以360º全回转,正常航行时使用海上模式,推进器只能在左右35º…

    2022年6月21日
    34
  • Kali安装教程(VMWare)

    Kali安装教程(VMWare)1.下载镜像及相关1.1下载镜像文件下载链接:https://www.kali.org/downloads/选择自己需要的版本下载,根据经验先下载种子文件(torrent)再用迅雷下载网速是最有保证的。1.2kali各版本说明Kali2.0使用Linux4.0内核,基于Debian8(DebianJessie)Kali—默认版本,Gnome3桌面,我一直对Gn…

    2022年5月7日
    69
  • Spring Boot 中的异步调用[通俗易懂]

    Spring Boot 中的异步调用[通俗易懂]SpringBoot中的异步调用通常我们开发的程序都是同步调用的,即程序按照代码的顺序一行一行的逐步往下执行,每一行代码都必须等待上一行代码执行完毕才能开始执行。而异步编程则没有这个限制,代码的调用不再是阻塞的。所以在一些情景下,通过异步编程可以提高效率,提升接口的吞吐量。这节将介绍如何在SpringBoot中进行异步编程。要开启异步支持,首先得在SpringBoot入口类上加上@EnableAsync注解:@SpringBootApplication@EnableAsyncpublic

    2022年7月11日
    27
  • 网页title图标_php 数据库显示在页面并能修改

    网页title图标_php 数据库显示在页面并能修改在生成的pdf文件的页眉设置logo有以下解决方案重新定义TCPDF中的K_PATH_IMAGES常量(define(‘K_PATH_IMAGES’,xxxx),需要定义在加载tcpdf.php之前)##示例$logo=”xxxx”;//相对地址$pdf->SetHeaderData(PDF_HEADER_LOGO,PDF_HEADER_LOGO_WIDTH,”标题”,…

    2025年9月5日
    4

发表回复

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

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