Hmily(1)

Hmily(1)1. Hmily是个高性能异步分布式事务TCC框架,具体包含SpringAOP,Disruptor,Dubbo等框架,当然还有其他的RPC框架。源码在https://github.com/yu199195/hmily,本文以duubo调用,mysql存储事务日志,kryo序列化为主,主要以下单支付减库存减余额为例,注解为Hmily,确认方法,取消方法和本次的tyr操作方法参数应该保持一致。前两个…

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

1. Hmily是个高性能异步分布式事务TCC框架,具体包含Spring AOP,Disruptor,Dubbo等框架,当然还有其他的RPC框架。源码在https://github.com/yu199195/hmily,本文以duubo调用,mysql存储事务日志,kryo序列化为主,主要以下单支付减库存减余额为例,注解为Hmily,确认方法,取消方法和本次的tyr操作方法参数应该保持一致。前两个方法名配置在注解上。

@Hmily(confirmMethod = "confirmOrderStatus", cancelMethod = "cancelOrderStatus")
    public void makePayment(Order order) {
        order.setStatus(OrderStatusEnum.PAYING.getCode());
        orderMapper.update(order);
        //做库存和资金账户的检验工作 这里只是demo 。。。
       /* final AccountDO accountDO = accountService.findByUserId(order.getUserId());
        if (accountDO.getBalance().compareTo(order.getTotalAmount()) <= 0) {
            throw new HmilyRuntimeException("余额不足!");
        }
        final InventoryDO inventory = inventoryService.findByProductId(order.getProductId());

        if (inventory.getTotalInventory() < order.getCount()) {
            throw new HmilyRuntimeException("库存不足!");
        }*/
        //扣除用户余额
        AccountDTO accountDTO = new AccountDTO();
        accountDTO.setAmount(order.getTotalAmount());
        accountDTO.setUserId(order.getUserId());
        accountService.payment(accountDTO);
        //进入扣减库存操作
        InventoryDTO inventoryDTO = new InventoryDTO();
        inventoryDTO.setCount(order.getCount());
        inventoryDTO.setProductId(order.getProductId());
        inventoryService.decrease(inventoryDTO);
    }

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Hmily {

    /**
     * Confirm method string.
     *
     * @return the string
     */
    String confirmMethod() default "";

    /**
     * Cancel method string.
     *
     * @return the string
     */
    String cancelMethod() default "";

    /**
     * Pattern pattern enum.
     *
     * @return the pattern enum
     */
    PatternEnum pattern() default PatternEnum.TCC;

}

应用配置文件如下applicationContext.xml:spring-dubbo.xml:

 <context:component-scan base-package="org.dromara.hmily.*"/>
    <aop:aspectj-autoproxy expose-proxy="true"/>
    <bean id="hmilyTransactionBootstrap" class="org.dromara.hmily.core.bootstrap.HmilyTransactionBootstrap">
        <property name="serializer" value="kryo"/>
        <property name="recoverDelayTime" value="120"/>
        <property name="retryMax" value="3"/>
        <property name="scheduledDelay" value="120"/>
        <property name="scheduledThreadMax" value="4"/>
        <property name="repositorySupport" value="db"/>
        <property name="started" value="false"/>
        <property name="hmilyDbConfig">
            <bean class="org.dromara.hmily.common.config.HmilyDbConfig">
                <property name="url"
                          value="jdbc:mysql://192.168.1.98:3306/tcc?useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </bean>
        </property>
    </bean>

    <import resource="spring-dubbo.xml"/>



  <dubbo:application name="order_service"/>


    <dubbo:registry protocol="zookeeper" address="192.168.1.84:2181"/>

    <dubbo:protocol name="dubbo" port="20886"
                    server="netty" client="netty"
                    charset="UTF-8" threadpool="fixed" threads="500"
                    queues="0" buffer="8192" accepts="0" payload="8388608"/>

    <dubbo:reference timeout="50000"
                     interface="org.dromara.hmily.demo.dubbo.inventory.api.service.InventoryService"
                     id="inventoryService"
                     retries="0" check="false" actives="20"/>
    <dubbo:reference timeout="50000"
                     interface="org.dromara.hmily.demo.dubbo.account.api.service.AccountService"
                     id="accountService"
                     retries="0" check="false" actives="20"/>

2. 初始化启动类HmilyTransactionBootstrap,实现一些类的初始化,保存spring上下文容器。

public class HmilyTransactionBootstrap extends HmilyConfig implements ApplicationContextAware {

    private final HmilyInitService hmilyInitService;

    @Autowired
    public HmilyTransactionBootstrap(final HmilyInitService hmilyInitService) {
        this.hmilyInitService = hmilyInitService;
    }

    @Override
    public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
        SpringBeanUtils.getInstance().setCfgContext((ConfigurableApplicationContext) applicationContext);
        start(this);
    }

    private void start(final HmilyConfig hmilyConfig) {
        hmilyInitService.initialization(hmilyConfig);
    }
}

开始初始化类的处理化HmilyInitServiceImpl,注入数据存储协调了HmilyCoordinatorServiceImpl,加载spi支持类。也就是实例化序列化类KryoSerializer,事务日志存储类JdbcCoordinatorRepository,并注册到容器中。

public void initialization(final HmilyConfig hmilyConfig) {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> LOGGER.info("hmily shutdown now")));
        try {
            loadSpiSupport(hmilyConfig);
            hmilyCoordinatorService.start(hmilyConfig);
        } catch (Exception ex) {
            LogUtil.error(LOGGER, " hmily init exception:{}", ex::getMessage);
            System.exit(1);
        }
        new HmilyLogo().logo();
    }

private void loadSpiSupport(final HmilyConfig hmilyConfig) {
        //spi serialize
        final SerializeEnum serializeEnum = SerializeEnum.acquire(hmilyConfig.getSerializer());
        final ServiceLoader<ObjectSerializer> objectSerializers = ServiceBootstrap.loadAll(ObjectSerializer.class);
        final ObjectSerializer serializer = StreamSupport.stream(objectSerializers.spliterator(), false)
                .filter(objectSerializer -> Objects.equals(objectSerializer.getScheme(), serializeEnum.getSerialize()))
                .findFirst().orElse(new KryoSerializer());
        //spi repository
        final RepositorySupportEnum repositorySupportEnum = RepositorySupportEnum.acquire(hmilyConfig.getRepositorySupport());
        final ServiceLoader<HmilyCoordinatorRepository> recoverRepositories = ServiceBootstrap.loadAll(HmilyCoordinatorRepository.class);
        final HmilyCoordinatorRepository repository = StreamSupport.stream(recoverRepositories.spliterator(), false)
                .filter(recoverRepository -> Objects.equals(recoverRepository.getScheme(), repositorySupportEnum.getSupport()))
                .findFirst().orElse(new JdbcCoordinatorRepository());
        repository.setSerializer(serializer);
        SpringBeanUtils.getInstance().registerBean(HmilyCoordinatorRepository.class.getName(), repository);
    }

启动HmilyCoordinatorServiceImpl#start,也就是创建数据库表。

 public void start(final HmilyConfig hmilyConfig) {
        final String repositorySuffix = buildRepositorySuffix(hmilyConfig.getRepositorySuffix());
        coordinatorRepository = SpringBeanUtils.getInstance().getBean(HmilyCoordinatorRepository.class);
        coordinatorRepository.init(repositorySuffix, hmilyConfig);
    }

3. 开始执行请求,这里会先执行切面方法,切面类是DubboHmilyTransactionAspect,这里会设置他的排序值,因为在构建增强器时会根据这个排序值进行从小到大排序AbstractAdvisorAutoProxyCreator#sortAdvisors(eligibleAdvisors);该类会被首先执行,他的切点在注解Hmily上,

   @Pointcut("@annotation(org.dromara.hmily.annotation.Hmily)")
    public void hmilyInterceptor() {
    }

@Around("hmilyInterceptor()")
    public Object interceptTccMethod(final ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        return hmilyTransactionInterceptor.interceptor(proceedingJoinPoint);
    }

DubboHmilyTransactionInterceptor#interceptor,因为这个时候还没有经过dubbo的过滤器调用,所以这个context会为空。这个ThreadLocal也为空,主要是用来存储事务上下文的。

public Object interceptor(final ProceedingJoinPoint pjp) throws Throwable {
        final String context = RpcContext.getContext().getAttachment(CommonConstant.HMILY_TRANSACTION_CONTEXT);
        HmilyTransactionContext hmilyTransactionContext;
        if (StringUtils.isNoneBlank(context)) {
            hmilyTransactionContext = GsonUtils.getInstance().fromJson(context, HmilyTransactionContext.class);
            RpcContext.getContext().getAttachments().remove(CommonConstant.HMILY_TRANSACTION_CONTEXT);
        } else {
            hmilyTransactionContext = HmilyTransactionContextLocal.getInstance().get();
        }
        return hmilyTransactionAspectService.invoke(hmilyTransactionContext, pjp);
    }

HmilyTransactionAspectServiceImpl#invoke获取对应的处理器然后进行下一步调用。

 public Object invoke(final HmilyTransactionContext hmilyTransactionContext, final ProceedingJoinPoint point) throws Throwable {
        final Class clazz = hmilyTransactionFactoryService.factoryOf(hmilyTransactionContext);
        final HmilyTransactionHandler txTransactionHandler = (HmilyTransactionHandler) SpringBeanUtils.getInstance().getBean(clazz);
        return txTransactionHandler.handler(point, hmilyTransactionContext);
    }

HmilyTransactionFactoryServiceImpl根据上下文的内容获取对应的处理器,第一次获取StarterHmilyTransactionHandler

 public Class factoryOf(final HmilyTransactionContext context) {
        if (Objects.isNull(context)) {
            return StarterHmilyTransactionHandler.class;
        } else {
            //why this code?  because spring cloud invoke has proxy.
            if (context.getRole() == HmilyRoleEnum.SPRING_CLOUD.getCode()) {
                context.setRole(HmilyRoleEnum.START.getCode());
                return ConsumeHmilyTransactionHandler.class;
            }
            // if context not null and role is inline  is ParticipantHmilyTransactionHandler.
            if (context.getRole() == HmilyRoleEnum.LOCAL.getCode()) {
                return LocalHmilyTransactionHandler.class;
            } else if (context.getRole() == HmilyRoleEnum.START.getCode()
                    || context.getRole() == HmilyRoleEnum.INLINE.getCode()) {
                return ParticipantHmilyTransactionHandler.class;
            }
            return ConsumeHmilyTransactionHandler.class;
        }
    }

 

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

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

(0)
上一篇 2022年5月22日 上午6:40
下一篇 2022年5月22日 上午6:40


相关推荐

  • 不是单组分组函数「建议收藏」

    不是单组分组函数「建议收藏」问题:一:SELECT tablespace_name, SUM(bytes) freeFROM dba_free_space不是单组分组函数原因: 1、如果程序中使用了分组函数,则有两种情况可以使用:程序中存在group by,并指定了分组条件,这样可以将分组条件一起查询出来改为:  SELECT tablespace_name, SUM(bytes) freeFROM dba_free_spa…

    2022年6月30日
    39
  • 无类路由计算方法_actin

    无类路由计算方法_actin给定一个包含 n 个点 m 条边的有向图,并给定每条边的容量和费用,边的容量非负。图中可能存在重边和自环,保证费用不会存在负环。求从 S 到 T 的最大流,以及在流量最大时的最小费用。输入格式第一行包含四个整数 n,m,S,T。接下来 m 行,每行三个整数 u,v,c,w,表示从点 u 到点 v 存在一条有向边,容量为 c,费用为 w。点的编号从 1 到 n。输出格式输出点 S 到点 T 的最大流和流量最大时的最小费用。如果从点 S 无法到达点 T 则输出 0 0。数据范围2≤n≤50

    2022年8月9日
    10
  • linux pycharm激活码[免费获取][通俗易懂]

    (linux pycharm激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月21日
    245
  • css属性margin是什么意思_css中position的属性

    css属性margin是什么意思_css中position的属性深入理解css中的margin属性之前我一直认为margin属性是一个非常简单的属性,但是最近做项目时遇到了一些问题,才发现margin属性还是有一些“坑”的,下面我会介绍margin的基本知识以及

    2022年8月1日
    8
  • 计算机丢失ac1st24,安装CAD时因计算机丢失ac1st16.dll是什么意思?

    计算机丢失ac1st24,安装CAD时因计算机丢失ac1st16.dll是什么意思?今天安装了 AutoCAD2006 安装完成后运行 系统提示找不到 AC1ST16 DLL 文件 ps 我的系统是 windows7 然后就搜索看看系统里面有没有 AC1ST16 DLL 这个文件 搜索结果是有的 我就纳闷着为什么明明有 AC1ST16 DLL 这个文件却说没有呢 况且以前装没有问题 现在就有问题了 查看了 AutoCAD 的知识库 顿时大悟啊 原文如下 问题在启动 Autodesk 产品时 出现

    2026年3月17日
    2
  • Map<String,Object>转为JSONObject ,JSONObject 转为JsonObject,JsonObject转为JsonElement

    Map<String,Object>转为JSONObject ,JSONObject 转为JsonObject,JsonObject转为JsonElementpackagecom.tianjian.property.jieshuns.service;importjava.util.Map;importjava.util.Properties;importorg.apache.http.HttpStatus;importorg.apache.http.client.methods.CloseableHttpRes

    2022年5月15日
    46

发表回复

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

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