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 一样的用法