1、报错如下
问题:
在使用seata,使用 spring-cloud-alibaba-seata 和 spring-cloud-starter-sleuth 两个maven依赖时,在接口调用的时候,会报错:
Caused by: com.netflix.client.ClientException: Load balancer does not have available server for client: 192.168.4.15
at com.netflix.loadbalancer.LoadBalancerContext.getServerFromLoadBalancer(LoadBalancerContext.java:483) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:184) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]
at rx.Observable.unsafeSubscribe(Observable.java:10327) ~[rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94) ~[rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42) ~[rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.3.8.jar:1.3.8]
at rx.Observable.subscribe(Observable.java:10423) ~[rxjava-1.3.8.jar:1.3.8]
at rx.Observable.subscribe(Observable.java:10390) ~[rxjava-1.3.8.jar:1.3.8]
at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:443) ~[rxjava-1.3.8.jar:1.3.8]
at rx.observables.BlockingObservable.single(BlockingObservable.java:340) ~[rxjava-1.3.8.jar:1.3.8]
at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:112) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]
at org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:83) ~[spring-cloud-openfeign-core-2.2.2.RELEASE.jar:2.2.2.RELEASE]
... 120 common frames omitted
2、官方修改建议:
Spring Cloud Sleuth默认通过TraceFeignClientAutoConfiguration提供feign的集成,可以设置spring.sleuth.feign.enabled为false来使其无效。
但是这种修改方式把sleuth关闭了,导致在zipkin控制台看到的接口调用栈都是没有任何关联的:如果你需要使用seata,但是又不想关闭sleuth,则本篇博客就来解决这个问题。
1、去除 spring-cloud-alibaba-seata 依赖。
2、添加以下依赖
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.2.0</version>
</dependency>
3、最好在公共工程里新建Feign拦截器类,这样所有的微服务只需要依赖公共工程就可以了,下面的几个类也是一样的
package com.ahies.stm.app.interceptor;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import io.seata.core.context.RootContext;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SeataFeignInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate request) {
String xid = RootContext.getXID();
if (xid != null && !xid.trim().isEmpty()) {
log.debug("seata - feign add seata-xid http request header [{}]", xid);
request.header(RootContext.KEY_XID, xid);
}
}
}
4、新建Feign拦截器的配置类
package com.ahies.stm.app.conf;
import com.ahies.stm.app.interceptor.SeataFeignInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
public class SeataFeignConfiguration {
@Bean
@ConditionalOnMissingBean
public SeataFeignInterceptor seataFeignInterceptor() {
return new SeataFeignInterceptor();
}
}
5、新建开启分布式事务注解类
package com.ahies.stm.app.anno;
import com.ahies.stm.app.conf.SeataFeignConfiguration;
import io.seata.integration.http.HttpAutoConfiguration;
import org.springframework.context.annotation.Import;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import({SeataFeignConfiguration.class, HttpAutoConfiguration.class})
public @interface EnableSeata {
}
6、使用方法:在 application启动类上加上@EnableSeata 注解
7、配置文件还是和spring-cloud-alibaba-seata 一样的用法