解决 Seata 与 Sleuth 引起的冲突
版本:
Spring Cloud : Hoxton.SR4
Spring Boot: 2.2.5.RELEASE
Spring Cloud Alibaba:2.2.1.RELEASE
Seata:1.1.0
spring-cloud-starter-sleuth:2.2.3.RELEASE
1.Seata 引入 Sleuth 后报错
整合了 Alibaba 的 nacos、sentinel、seata,分布式事务运行正常,整合 sleuth 之后就报错了:
com.netflix.client.ClientException: Load balancer does not have available server for client:
2.加配置
百度问题,无意中看到这个配置,也不是解决这个问题的,只是觉得问题出在 Feign 上,就加上试试。
feign:
hystrix:
enabled: true
加了配置后报错
The bean 'feignHystrixBuilder',
defined in class path resource
[org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignClientAutoConfiguration.class],
could not be registered. A bean with that name has already been defined in class path resource
[com/alibaba/cloud/seata/feign/SeataFeignClientAutoConfiguration.class] and overriding is disabled.
3.看源码
TraceFeignClientAutoConfiguration:
// 类上的注解
@ConditionalOnProperty(
value = {"spring.sleuth.feign.enabled"},
matchIfMissing = true
)
@Bean
@Scope("prototype")
@ConditionalOnClass(
name = {"com.netflix.hystrix.HystrixCommand", "feign.hystrix.HystrixFeign"}
)
@ConditionalOnProperty(
name = {"feign.hystrix.enabled"},
havingValue = "true"
)
Builder feignHystrixBuilder(BeanFactory beanFactory) {
return SleuthHystrixFeignBuilder.builder(beanFactory);
}
SeataFeignClientAutoConfiguration:
@Bean
@Scope("prototype")
@ConditionalOnClass(
name = {"com.netflix.hystrix.HystrixCommand"}
)
@ConditionalOnProperty(
name = {"feign.hystrix.enabled"},
havingValue = "true"
)
Builder feignHystrixBuilder(BeanFactory beanFactory) {
return SeataHystrixFeignBuilder.builder(beanFactory);
}
这两个类中都有创建 Bean:feignHystrixBuilder
只能留一个
4.加配置
spring:
sleuth:
feign:
enabled: false
报错:
Field accountService in com.orderplus.demo.provider.service.impl.OrderServiceImpl required a single bean, but 2 were found:
- feignHystrixBuilder: defined by method 'feignHystrixBuilder' in class path resource [com/alibaba/cloud/seata/feign/SeataFeignClientAutoConfiguration.class]
- feignSentinelBuilder: defined by method 'feignSentinelBuilder' in class path resource [com/alibaba/cloud/seata/feign/SeataFeignClientAutoConfiguration.class]
5.改配置
注释掉
#feign:
# hystrix:
# enabled: true
6.重启
分布式事务正常,Sleuth 不正常了
以上步骤可以忽略
7.配置 Seata 拦截
新建 SetSeataInterceptor 类,拦截 xid
import feign.RequestInterceptor;
import feign.RequestTemplate;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Component;
@Component
@ConditionalOnClass({RequestInterceptor.class, GlobalTransactional.class})
public class SetSeataInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
String currentXid = RootContext.getXID();
if (StringUtils.isNotEmpty(currentXid)) {
requestTemplate.header(RootContext.KEY_XID, currentXid);
}
}
}
8.启动类排除 SeataFeignClientAutoConfiguration.class
@SpringBootApplication(exclude = {SeataFeignClientAutoConfiguration.class})
9.其他配置
这个是默认为 true,可以不配置
spring:
sleuth:
feign:
enabled: true
10.重启
问题终于解决了