分布式_事务_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;
    }
}

3.加载spi

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

    /**
     * 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);
    }

八、参考资料

1.Java之SPI机制

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏架构师之旅

《Spring敲门砖之基础教程第一季》 第二章(1) Spring框架之IOC首例-HelloWorld

回顾 上一章我们主要学习了Spring的一些理论知识,对Spring框架有了一个总体的概括,大家应该在头脑里形成一个初步的印象,接下来我们就会针对Spring框...

19810
来自专栏JetpropelledSnake

Django学习笔记之利用Form和Ajax实现注册功能

1615
来自专栏Java架构师历程

solr

Solr它是一种开放源码的、基于 Lucene Java 的搜索服务器,易于加入到 Web 应用程序中。Solr 提供了层面搜索(就是统计)、命中醒目显示并且支...

2882
来自专栏后端之路

redis无法获取连接Could not get a resource from the pool分析

背景 随着系统使用用户上升,我们也愈发多的使用到了redis组件! 比如在做session共享时 tomcat使用redis做session 参考https:/...

59210
来自专栏吉浦迅科技

DAY71:阅读Device-side Launch from PTX

我们正带领大家开始阅读英文的《CUDA C Programming Guide》,今天是第71天,我们正在讲解CUDA 动态并行,希望在接下来的30天里,您可以...

1132
来自专栏纯洁的微笑

springboot(十一):Spring boot中mongodb的使用

mongodb是最早热门非关系数据库的之一,使用也比较普遍,一般会用做离线数据分析来使用,放到内网的居多。由于很多公司使用了云服务,服务器默认都开放了外网地址,...

3416
来自专栏GopherCoder

『No19: Gorm 上手指南』

如果你是做后端开发的,日常工作中,除了熟悉编程语言之外,数据库怕是最常用的技术了吧。

5491
来自专栏一个番茄说

Swift中防止ptrace依附

在移动开发中,安全是一个很重要的话题,当然安全是没有绝对的,只能说尽可能的提高安全性。在iOS的开发中,为了防止别人窥视我们的App,我们得采用一些手段来进行防...

1083
来自专栏coolblog.xyz技术专栏

Spring IOC 容器源码分析系列文章导读

Spring 是一个轻量级的企业级应用开发框架,于 2004 年由 Rod Johnson 发布了 1.0 版本。经过十几年的迭代,现在的 Spring 框架已...

1393
来自专栏工科狗和生物喵

FreeRTOS-Qemu 实现三任务同步通信机制以及API信息

---- 1. 本次作业的考察要点: 作业地址:https://github.com/HustWolfzzb/STM32F429DiscoveryFreeRTO...

1K6

扫码关注云+社区