seata       

seata

使用两阶段提交模型

image-20211229175534501

@Bean("originOrder") 
@ConfigurationProperties(prefix = "spring.datasource.order") 
public DataSource dataSourceMaster() { 
  return new DruidDataSource(); 
}
@Bean(name = "order") 
public DataSourceProxy masterDataSourceProxy(@Qualifier("originOrder") DataSource dataSource) { 
  return new DataSourceProxy(dataSource); 
}

image-20211213131956984

@Bean("dataSource")
    public DataSource dataSource(DruidDataSource druidDataSource) {
        // DataSourceProxy for AT mode
        // return new DataSourceProxy(druidDataSource);

        // DataSourceProxyXA for XA mode
        return new DataSourceProxyXA(druidDataSource);
    }

AT

image-20211215083422679

两阶段提交协议的演变:

写隔离

io.seata.rm.datasource.ConnectionProxy#doCommit

注册分支事务

插入undo_log

本地事务commit

@transactional

通过ProxyTransactionManagementConfiguration,注入一个BeanFactoryTransactionAttributeSourceAdvisor bean

seata

通过注入GlobalTransactionScanner后置处理器在postProcessAfterInitialization的时候做代理

io.seata.spring.annotation.GlobalTransactionScanner#wrapIfNecessary

seata feign

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Client.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class SeataFeignClientAutoConfiguration {

	@Bean
	@Scope("prototype")
	@ConditionalOnClass(name = "com.netflix.hystrix.HystrixCommand")
	@ConditionalOnProperty(name = "feign.hystrix.enabled", havingValue = "true")
	Feign.Builder feignHystrixBuilder(BeanFactory beanFactory) {
		return SeataHystrixFeignBuilder.builder(beanFactory);
	}

	@Bean
	@Scope("prototype")
	@ConditionalOnClass(name = "com.alibaba.csp.sentinel.SphU")
	@ConditionalOnProperty(name = "feign.sentinel.enabled", havingValue = "true")
	Feign.Builder feignSentinelBuilder(BeanFactory beanFactory) {
		return SeataSentinelFeignBuilder.builder(beanFactory);
	}

	@Bean
	@ConditionalOnMissingBean
	@Scope("prototype")
	Feign.Builder feignBuilder(BeanFactory beanFactory) {
		return SeataFeignBuilder.builder(beanFactory);
	}

	@Configuration(proxyBeanMethods = false)
	protected static class FeignBeanPostProcessorConfiguration {

		@Bean
		SeataBeanPostProcessor seataBeanPostProcessor(
				SeataFeignObjectWrapper seataFeignObjectWrapper) {
			return new SeataBeanPostProcessor(seataFeignObjectWrapper);
		}

		@Bean
		SeataContextBeanPostProcessor seataContextBeanPostProcessor(
				BeanFactory beanFactory) {
			return new SeataContextBeanPostProcessor(beanFactory);
		}

		@Bean
		SeataFeignObjectWrapper seataFeignObjectWrapper(BeanFactory beanFactory) {
			return new SeataFeignObjectWrapper(beanFactory);
		}

	}

}

com.alibaba.cloud.seata.feign.SeataContextBeanPostProcessor

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
      throws BeansException {
   if (bean instanceof FeignContext && !(bean instanceof SeataFeignContext)) {
      return new SeataFeignContext(getSeataFeignObjectWrapper(),
            (FeignContext) bean);
   }
   return bean;
}

com.alibaba.cloud.seata.feign.SeataFeignObjectWrapper#wrap

Object wrap(Object bean) {
   if (bean instanceof Client && !(bean instanceof SeataFeignClient)) {
      if (bean instanceof LoadBalancerFeignClient) {
         LoadBalancerFeignClient client = ((LoadBalancerFeignClient) bean);
         return new SeataLoadBalancerFeignClient(client.getDelegate(), factory(),
               clientFactory(), this);
      }
      if (bean instanceof FeignBlockingLoadBalancerClient) {
         FeignBlockingLoadBalancerClient client = (FeignBlockingLoadBalancerClient) bean;
         return new SeataFeignBlockingLoadBalancerClient(client.getDelegate(),
               beanFactory.getBean(BlockingLoadBalancerClient.class), this);
      }
      return new SeataFeignClient(this.beanFactory, (Client) bean);
   }
   return bean;
}

该方式和sleuth类似

整合了ribbonsleuth: 会获取TraceFeignClient实例,该实例是对LoadBalanceFeignClient的一种包装,实现方式通过BeanPostProcessor实现:FeignBeanPostProcessor中定义了包装逻辑:

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        return this.traceFeignObjectWrapper.wrap(bean);
    }

通过wrap方法最终返回TraceFeignClient实例。

集成Feign和ribbon组件

https://blog.csdn.net/nandao158/article/details/110725287

https://www.cnblogs.com/crazymakercircle/p/11965726.html

com.alibaba.cloud.seata.feign.SeataFeignClientAutoConfiguration#feignBuilder

@Bean
@ConditionalOnMissingBean
@Scope("prototype")
Feign.Builder feignBuilder(BeanFactory beanFactory) {
   return SeataFeignBuilder.builder(beanFactory);
}
static Feign.Builder builder(BeanFactory beanFactory) {
   return Feign.builder().client(new SeataFeignClient(beanFactory));
}

com.alibaba.cloud.seata.feign.SeataFeignClient#execute

@Override
public Response execute(Request request, Request.Options options) throws IOException {

   Request modifiedRequest = getModifyRequest(request);
   return this.delegate.execute(modifiedRequest, options);
}

private Request getModifyRequest(Request request) {

   String xid = RootContext.getXID();

   if (StringUtils.isEmpty(xid)) {
      return request;
   }

   Map<String, Collection<String>> headers = new HashMap<>(MAP_SIZE);
   headers.putAll(request.headers());

   List<String> seataXid = new ArrayList<>();
   seataXid.add(xid);
   headers.put(RootContext.KEY_XID, seataXid);

   return Request.create(request.method(), request.url(), headers, request.body(),
         request.charset());
}

参考

https://seata.io/zh-cn/docs/overview/what-is-seata.html

https://www.processon.com/view/link/5f743063e0b34d0711f001d2