使用两阶段提交模型
@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);
}
@Bean("dataSource")
public DataSource dataSource(DruidDataSource druidDataSource) {
// DataSourceProxy for AT mode
// return new DataSourceProxy(druidDataSource);
// DataSourceProxyXA for XA mode
return new DataSourceProxyXA(druidDataSource);
}
两阶段提交协议的演变:
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类似
整合了ribbon
和 sleuth
:
会获取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