Hmily 源码解析(二)—— 调用微服务

Hmily 源码解析(二)—— 调用微服务由于篇幅过长,将该模块单独拎出一节,接上文Hmily源码解析(二)——执行主体方法上文我们把主体方法的执行及Feign的相关配置讲解了,知道在调用微服务时把对应的HmilyTransactionContext实例以“HMILY_TRANSACTION_CONTEXT”为key作为请求参数一同发送过来,及调用微服务成功之后会把调用接口的方法(有@Hmily注解的)封装为HmilyPa…

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


  • 上文我们把主体方法的执行及Feign的相关配置讲解了,知道在调用微服务时把对应的HmilyTransactionContext实例以“HMILY_TRANSACTION_CONTEXT”为key作为请求参数一同发送过来,及调用微服务成功之后会把调用接口的方法(有@Hmily注解的)封装为HmilyParticipant实例异步存储到存储到HmilyTransaction实例中。

  • 现在接着讲在库存微服务接收到请求后会如何执行请求并做了哪些操作。

  • 如下请求调用一开就需要先进入Hmily切面程序

在这里插入图片描述
在这里插入图片描述

  • 根据前文,前面的类不再重复介绍,现在执行到了interceptor方法,首先这个请求刚开始,这个线程内还未存在HmilyTransactionContext实例。所以到下面这个else模块,这里很重要,我们记得前面在请求头里面有存在“HMILY_TRANSACTION_CONTEXT”为key的HmilyTransactionContext实例信息,现在就从这里取出来了。致此我们了解了微服务间是如何实现关于事务信息的通信。

在这里插入图片描述

  • 我们现在来看一下factoryof方法里面是如何选择处理类的,传过来的角色为发起者(HmilyRoleEnum.START)所以选择了ParticipantHmilyTransactionHandler去执行后续操作。

在这里插入图片描述

  • 目前我们的状态是TRYING 所以我们目前只要关注红色框内的代码即可

在这里插入图片描述

  • 先看一下preTryParticipant内做了什么,首先新建了一个HmilyTransaction实例,这个实例是存储在hmily_inventory_service表中的,和前一个HmilyTransaction实例不是同一个实例了。
  • buildHmilyTransaction函数前面讲过,根据参数的不同,新建的这个HmilyTransaction实例的角色为提供者(PROVIDER),transId为传入的transId,运行状态为开始执行try阶段(PRE_TRY),其它的类信息,HmilyParticipant实例信息是从本次切面对象(decrease函数及对应的Hmily注解信息)上获取的。目前HmilyParticipant只有decrease函数本身。
  • 将生成的HmilyTransaction实例存储到缓存里(缓存和线程就无关了,而是以transId为key存储,只要在有效时间内都能获取得到),及异步保存到hmily_inventory_service表中。
  • HmilyTransactionContext将角色改为本地调用( LOCAL),又一个角色状态现在被使用了!而且HmilyTransaction实例并没有一起被修改,而微服务的调用者的角色状态也仍是发起者(START),大体可以猜测本地调用( LOCAL)可能是个中间状态,在这次使用完之后就会丢弃。
  • 然后HmilyTransactionContext绑定到本地线程。

在这里插入图片描述
在这里插入图片描述

  • preTry之后第一步执行主体方法,主体方法内部非常简单,就是一条数据库操作就不再述了,接着如果执行主体方法成功没问题,则修改执行状态为try完成(TRYING),并异步保存到数据库中。如果执行失败报出异常则发起请求异步删除hmilyTransaction实例,并向上继续抛出异常(抛给微服务调用者),再往下finally里就是线程结束时的收尾工作,不再复述了。

在这里插入图片描述

  • 微服务的try阶段就完成了,之前说的本地调用( LOCAL)状态好像没用到,的确demo里没有覆盖这么全面,没有案例我也先不去分析了。

  • 我们可以再简单介绍一下CONFIRMING,与CANCELING的情况,当微服务第二次接收到请求时,状态就会变成CONFIRMING或者CANCELING。

  • 首先他们的第一步都是通过transId从缓存中获取HmilyTransaction实例。

    • 为什么要这样做,不直接从数据库获取HmilyTransaction实例?我猜测是这样的,上文异步保存HmilyTransaction实例到数据库与第二次请求的时间之间谁快谁慢这是说不准的,有可能第二次请求已经来了,但是数据库中还未保存HmilyTransaction实例,如果这时候去数据库中去可能就会返回null。在缓存中存储一个HmilyTransaction实例就可以解决这个问题,如果第二次请求更快则直接取缓存数据,反之第二次请求由于某些原因特别慢导致缓存已经失效了,但是这时间足以保证HmilyTransaction实例保存到数据中,这时依然能够通过HmilyTransactionGuavaCacheManager从数据库中获取该实例(见GuavaCache的获取机制)。
  • 接着就是根据HmilyTransaction实例执行对应confirm方法或cancel方法。

在这里插入图片描述

  • 我们看一下confirm方法做了什么,cancel方法类似就不分析了
  • 1.修改状态为CONFIRM阶段(CONFIRMING)
  • 2.前文说了,hmilyParticipant实例只有一个就是decrease函数本身,如何通过反射调用Hmily注解里面配置的confirm方法(confirmMethod)。如果有执行失败的hmilyParticipant会存储在failList集合里面。
  • 3.,然后执行executeHandler函数,如下二图,成功删除相应的HmilyTransaction实例信息,如果有失败案例,则异步修改HmilyTransaction实例的hmilyParticipants集合(只保留执行失败的hmilyParticipant集合),后面定时器会再根据日志去定时执行这些hmilyParticipants集合,直到所有的hmilyParticipant被正确处理,或超过执行重试次数报个管理员手工处理。关于定时器重试执行的内容这边先按下不表。
  • 对于这个demo的情况就是,hmilyParticipants集合里只有一个hmilyParticipant实例,如果confirm失败了,就通过定时器不停的重试执行,cancel失败如是,直到超过最大重试次数。

在这里插入图片描述

在这里插入图片描述

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

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

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


相关推荐

  • mybatis底层通过什么实现_priorityqueue java

    mybatis底层通过什么实现_priorityqueue java一、概述最近接触了一些项目,发现很多项目最开始的时候Service接口和实现类一个方法都没有,通过继承通用底层能够使用基本的增删改查操作了。这种骚操作以前听过但是着实没有亲手实现过,今天参考着自己实

    2022年8月16日
    7
  • 怎么在linux装samba服务器,在linux上装配置samba服务器.doc

    怎么在linux装samba服务器,在linux上装配置samba服务器.doc在linux上装配置samba服务器在linux上安装配置samba服务器在linux上安装配置samba服务器在这给大家介绍一个不错的家伙,samba服务。如果您正在犯愁,如何在Windows和Linux之间实现资源共享,就请看看这篇详解,希望能帮您解决困扰。先简单介绍一下,SMB(ServerMessagesBlock,信息服务块)是在局域网上共享文件和打印机的一种协议,通过它可以使局域网…

    2022年5月21日
    35
  • 二叉查找树实现原理分析

    二叉查找树实现原理分析

    2022年3月2日
    60
  • Brocade 光纤交换机下zone划分 — 基础篇

    Brocade 光纤交换机下zone划分 — 基础篇###Brocade光纤交换机下zone划分—基础篇#Brocade5320/SAN交换机/zone划分/>>INTRO:zone的配置,在逻辑上将连接在SAN网络中的设备划分为不同区域,隔离网络中主机和设备。要实现这种SAN划分,可用在NameServer中隔离(Softwarezoning)或在数据转发时过滤数据包(Hardwarezonin

    2022年5月21日
    30
  • JAVA中interface接口的使用[通俗易懂]

    JAVA中interface接口的使用[通俗易懂]提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、interface是什么?二、关于interface的使用1.接口的格式代码例子12.用登录方法具体实现代码例子2:抽象类和接口之间的区别总结前言随着面向对象思想的发展,类的使用越来越方便,但是有时候类却不能实现对于方法的抽象,只能对于自己的属性的抽象。(所谓抽象简单理解为没有具体的实现)于是我们便在java语言中引出了一种接口的方式(interface)。(以下内容基于JAVA语言)提示:以下是本篇文章正文内容.

    2022年10月21日
    2
  • HTML+CSS实现炫酷的登录界面「建议收藏」

    HTML+CSS实现炫酷的登录界面「建议收藏」谢谢大家的支持,您的一键三连是罡罡同学前进的最大动力!一键三连一键三连一键三连一键三连一键三连一键三连HTML+CSS实现炫酷的登录界面上效果图!鼠标点击用户名或密码,字体会向上滑动,调节大小并高亮。鼠标放到登录按钮上,按钮可以高亮!下面是HTML的代码:<!DOCTYPEhtml><htmllang=”zh-CN”> <head> <metacharset=”utf-8″/> <meta

    2022年5月4日
    177

发表回复

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

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