seata源码分析-AT模式-开启全局事务
导读
分布式事务模式:AT
分布式调用场景:
1、客户端请求Business服务下单----》
2、Business通过Rpc调用Storage服务扣减库存----》
3、Business通过Rpc调用Order服务创建订单-----》
4、Order通过Rpc调用Account服务扣减用户余额
模块调用逻辑架构
代码结构
模块名称 | 模块描述 |
---|---|
samples-business | 分布式事务入口(TM) |
samples-account | 账户服务(RM) |
samples-order | 订单服务(RM) |
samples-storage | 库存服务(RM) |
samples-common | 公共模块 |
源码分析
源码分析需要拆分两部分来说明
1、项目启动时,seata客户端做了哪些准备工作?
2、客户端请求Business服务下单,seata客户端请求服务端开启全局事务是怎么实现的呢?
1 解析seata客户端初始化
1.1.1、初始化全局事务扫描器(GlobalTransactionScanner)
1.1.2、初始化TM Client,RM Client
1.1.3、生成代理类对象
1.1、初始化全局事务扫描器(GlobalTransactionScanner)
找到GlobalTransaction自动配置类
初始化扫描器类对象
@Configuration
@EnableConfigurationProperties({
SeataProperties.class})
public class GlobalTransactionAutoConfiguration {
private final ApplicationContext applicationContext;
private final SeataProperties seataProperties;
public GlobalTransactionAutoConfiguration(ApplicationContext applicationContext, SeataProperties seataProperties) {
this.applicationContext = applicationContext;
this.seataProperties = seataProperties;
}
@Bean
public GlobalTransactionScanner globalTransactionScanner() {
String applicationName = this.applicationContext.getEnvironment().getProperty("spring.application.name");
String txServiceGroup = this.seataProperties.getTxServiceGroup();
if (StringUtils.isEmpty(txServiceGroup)) {
txServiceGroup = applicationName + "-fescar-service-group";
this.seataProperties.setTxServiceGroup(txServiceGroup);
}
return new GlobalTransactionScanner(applicationName, txServiceGroup);
}
}
通过扫描器类发现继承,实现关系
1.2、初始化TM Client,RM Client
通过InitializingBean接口,实现afterPropertiesSet
初始化TM、RM客户端
@Override
public void afterPropertiesSet() {
if (disableGlobalTransaction) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Global transaction is disabled.");
}
return;
}
initClient();
}
初始化TM、RM netty客户端
private void initClient() {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Initializing Global Transaction Clients ... ");
}
if (StringUtils.isNullOrEmpty(applicationId) || StringUtils.isNullOrEmpty(txServiceGroup)) {
throw new IllegalArgumentException(String.format("applicationId: %s, txServiceGroup: %s", applicationId, txServiceGroup));
}
//init TM
TMClient.init(applicationId, txServiceGroup);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Transaction Manager Client is initialized. applicationId[{}] txServiceGroup[{}]", applicationId, txServiceGroup);
}
//init RM
RMClient.init(applicationId, txServiceGroup);
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Resource Manager is initialized. applicationId[{}] txServiceGroup[{}]", applicationId, txServiceGroup);
}
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Global Transaction Clients are initialized. ");
}
registerSpringShutdownHook();
}
registerSpringShutdownHook钩子函数,在Spring容器停止的时候关闭Netty连接
1.3、生成代理类对象
GlobalTransactionScanner通过继承AbstractAutoProxyCreator
重写wrapIfNecessary方法实现代理
@Override
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (disableGlobalTransaction) {
return bean;
}
try {
synchronized (PROXYED_SET) {
if (PROXYED_SET.contains(beanName)) {
return bean;
}
interceptor = null;
//check TCC proxy
if (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, applicationContext)) {
//TCC interceptor, proxy bean of sofa:reference/dubbo:reference, and LocalTCC
interceptor = new TccActionInterceptor(TCCBeanParserUtils.getRemotingDesc(beanName));
} else {
Class<?> serviceInterface = SpringProxyUtils.findTargetClass(bean);
Class<?>[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean);
if (!existsAnnotation(new Class[]{
serviceInterface})
&& !existsAnnotation(interfacesIfJdk)) {
return bean;
}
if (interceptor == null) {
interceptor = new GlobalTransactionalInterceptor(failureHandlerHook);
ConfigurationFactory.getInstance().addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,