解决【zipkin整合seata的时候远程调用服务连接不上的问题】

编程

问题:

    在使用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.106.18

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

 

官方修改建议:

Spring Cloud Sleuth默认通过TraceFeignClientAutoConfiguration提供feign的集成,可以设置spring.sleuth.feign.enabled为false来使其无效。

来自官方issues:https://github.com/seata/seata/issues/2544

但是这种修改方式把sleuth关闭了,导致在zipkin控制台看到的接口调用栈都是没有任何关联的:

      

 

         如果你需要使用seata,但是又不想关闭sleuth,则本篇博客就来解决这个问题。

 

 

解决思路:

在seata的官方文档中业务系统集成seata客户端,有五个步骤。在最后一个步骤:

步骤五:实现xid跨服务传递
    手动 参考源码integration文件夹下的各种rpc实现 module
    自动 springCloud用户可以引入spring-cloud-alibaba-seata,内部已经实现xid传递

这个意思也就是:需要把全局事务的xid,透传到构成全局事务的各个子服务中。

    自动透传xid,可以直接引用 spring-cloud-alibaba-seata  (由于这个包和sleuth冲突,所以我们主要看手动透传xid的方案。)

    手动透传xid,可以参考官方源码的实现: https://github.com/seata/seata/tree/develop/integration

这里我就以http的实现思路来简单说一下:

    如果构成全局事务的各个自服务是使用http协议的,比如使用的是SpringCloud。对于http协议透传xid的方式很简单:

    在consumer端,只需要获取到xid然后把xid放到请求头中;

    在provider端解析http的请求头,然后使用RootContext.bind(xid)绑定xid即可。

我们来看源码:

Consumer端:

      

Provider端:

      

 

 

解决方案:

    我们可以直接把 io.seata.integration.http.DefaultHttpExecutor 和 io.seata.integration.http.HttpAutoConfiguration 配置到项目中即可。

    但是如果我们使用的是SpringCloud,一般来说都会使用feign。那么我们就写一个feign拦截器来代替 DefaultHttpExecutor 。在provider端还是使用 HttpAutoConfiguration。

引入依赖:

首先,我们需要注意我们引入的maven依赖:

    引入 seata-spring-boot-starter ,但是 不要引入 spring-cloud-alibaba-seata。

    引入 seata-spring-boot-starter ,但是 不要引入 spring-cloud-alibaba-seata。

    引入 seata-spring-boot-starter ,但是 不要引入 spring-cloud-alibaba-seata。

<dependency>

<groupId>io.seata</groupId>

<artifactId>seata-spring-boot-starter</artifactId>

<version>1.1.0</version> <!-- 当前最新版本为1.1.0 -->

</dependency>

备注:对于 seata-all maven依赖是否引入都可以。seata-spring-boot-starter 依赖中已经包含了 seata-all,所以可以不用单独引入seata-all。

Feign拦截器

/**

* feign拦截器,获取xid并放到请求头中

*

* @author anxiaole

* @email 745024471@qq.com

* @date 2020/5/12 15:27

*/

@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);

}

}

}

Feign拦截器的配置:

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;

import org.springframework.context.annotation.Bean;

/**

* @author anxiaole

* @email 745024471@qq.com

* @date 2020/5/9 10:19

*/

public class SeataFeignConfiguration {

@Bean

@ConditionalOnMissingBean

public SeataFeignInterceptor seataFeignInterceptor() {

return new SeataFeignInterceptor();

}

}

EnableSeata注解

import com.pandora.common.seata.feign.SeataFeignConfiguration;

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;

import io.seata.integration.http.HttpAutoConfiguration;

/**

* <pre>

* 开启seata分布式事务

*

* 1、在application启动类上使用此注解

* 2、需要在application.yml中配置如下参数:

* {@code

*

* # Seata 配置项,对应 SeataProperties 类

* seata:

* application-id: ${spring.application.name} # Seata 应用编号,默认为 ${spring.application.name}

* tx-service-group: my-application-group # Seata 事务组编号,用于 TC 集群名

* # 服务配置项,对应 ServiceProperties 类

* service:

* # 虚拟组和分组的映射

* vgroup-mapping:

* my-application-group: default

* # 分组和 Seata 服务的映射

* grouplist:

* default: localhost:8091

* }

*

* </pre>

*

* @author anxiaole

* @email 745024471@qq.com

* @date 2020/6/8 14:34

*/

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@Import({SeataFeignConfiguration.class, HttpAutoConfiguration.class})

public @interface EnableSeata {

}

 

使用方法:

1、在web application启动类上加上@EnableSeata 注解

      

2、在 application.yml中加入seata配置项:

      

 

 

参考:

学习seata概念首先需要看官方文档: http://seata.io/zh-cn/docs/overview/what-is-seata.html

了解了概念之后,尝试把官方的案例启动成功: http://seata.io/zh-cn/docs/user/quickstart.html

seata和自己项目进行整合,建议看  芋道源码  的博客: http://www.iocoder.cn/categories/Seata/

了解了原理之后、官方案例运行成功了,可以直接看 芋道源码 博客相关源码: https://github.com/YunaiV/SpringBoot-Labs/tree/master/labx-17

以上是 解决【zipkin整合seata的时候远程调用服务连接不上的问题】 的全部内容, 来源链接: utcz.com/z/517219.html

回到顶部