zoukankan      html  css  js  c++  java
  • 分布式_事务_02_2PC框架raincat源码解析

    一、前言

    上一节已经将raincat demo工程运行起来了,这一节来分析下raincat的源码

    二、协调者启动过程

    主要就是在启动类中通过如下代码来启动 netty

    nettyService.start()

    三、参与者启动过程

    1.参与者启动时序图

    参与者在启动过程中,主要做了如下4件事:

    (1)保存SpringContext上下文

    (2)通过加载spi,来使用用户自定义配置

    (3)启动Netty客户端,与txManager进行连接,并且维持心跳。

    (4)启动事务补偿任务,建表,定时补偿。

    (5)启动事务事件发布器。

    如下图:

    2.保存Spring上下文

    源码见  SpringBeanUtils 类,设置Spring 上下文,并提供spring  bean 的注册与获取方法。

    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more
     * contributor license agreements.  See the NOTICE file distributed with
     * this work for additional information regarding copyright ownership.
     * The ASF licenses this file to You under the Apache License, Version 2.0
     * (the "License"); you may not use this file except in compliance with
     * the License.  You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.raincat.core.helper;
    
    import org.springframework.context.ConfigurableApplicationContext;
    
    /**
     * SpringBeanUtils.
     * @author xiaoyu
     */
    public final class SpringBeanUtils {
    
        private static final SpringBeanUtils INSTANCE = new SpringBeanUtils();
    
        private ConfigurableApplicationContext cfgContext;
    
        private SpringBeanUtils() {
            if (INSTANCE != null) {
                throw new Error("error");
            }
        }
    
        /**
         * get SpringBeanUtils.
         * @return SpringBeanUtils
         */
        public static SpringBeanUtils getInstance() {
            return INSTANCE;
        }
    
        /**
         * acquire spring bean.
         *
         * @param type type
         * @param <T>  class
         * @return bean
         */
        public <T> T getBean(final Class<T> type) {
            return cfgContext.getBean(type);
        }
    
        /**
         * register bean in spring ioc.
         * @param beanName bean name
         * @param obj bean
         */
        public void registerBean(final String beanName, final Object obj) {
            cfgContext.getBeanFactory().registerSingleton(beanName, obj);
        }
    
        /**
         * set application context.
         * @param cfgContext application context
         */
        public void setCfgContext(final ConfigurableApplicationContext cfgContext) {
            this.cfgContext = cfgContext;
        }
    }
    View Code

    3.加载spi

        /**
         * load spi.
         *
         * @param txConfig {@linkplain TxConfig}
         */
        private void loadSpi(final TxConfig txConfig) {
            //spi  serialize
            final SerializeProtocolEnum serializeProtocolEnum
                    = SerializeProtocolEnum.acquireSerializeProtocol(txConfig.getSerializer());
            final ServiceLoader<ObjectSerializer> objectSerializers
                    = ServiceBootstrap.loadAll(ObjectSerializer.class);
            final ObjectSerializer serializer =
                    StreamSupport.stream(objectSerializers.spliterator(), false)
                            .filter(s -> Objects.equals(s.getScheme(), serializeProtocolEnum.getSerializeProtocol()))
                            .findFirst().orElse(new KryoSerializer());
    
            //spi  RecoverRepository support
            final CompensationCacheTypeEnum compensationCacheTypeEnum
                    = CompensationCacheTypeEnum.acquireCompensationCacheType(txConfig.getCompensationCacheType());
    
            final ServiceLoader<TransactionRecoverRepository> recoverRepositories
                    = ServiceBootstrap.loadAll(TransactionRecoverRepository.class);
            final TransactionRecoverRepository repository =
                    StreamSupport.stream(recoverRepositories.spliterator(), false)
                            .filter(r -> Objects.equals(r.getScheme(), compensationCacheTypeEnum.getCompensationCacheType()))
                            .findFirst().orElse(new JdbcTransactionRecoverRepository());
            //将compensationCache实现注入到spring容器
            repository.setSerializer(serializer);
            SpringBeanUtils.getInstance().registerBean(TransactionRecoverRepository.class.getName(), repository);
        }
    View Code

    (1)作用

    SPI的全名为Service Provider Interface,该机制其实就是为接口寻找服务实现类

    (2)如何使用

    当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。
    该文件里就是实现该服务接口的具体实现类。
    而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。

    八、参考资料

    1.Java之SPI机制

  • 相关阅读:
    archlinux .bash_history
    Ubuntu环境下挂载新硬盘
    软碟通 UltraISO U启替代品 Win32DiskImager 无设备 无盘符 无u盘 无优盘 解决方案 之diskpart
    delphi Integer overflow
    MSBuild Tools offline
    delphi synedit免费的拼写检查器dll
    git 自定义命令行
    lua编译
    gcc ar
    Windows Subsystem for Linux (WSL)挂载移动硬盘U盘 卸载 c d 盘
  • 原文地址:https://www.cnblogs.com/shirui/p/9674428.html
Copyright © 2011-2022 走看看