SpringCloud之OpenFeign

前言

本次我们来看看SpringCloud组件OpenFeign
目录如下:
SpringCloud之OpenFeign_第1张图片

1、Feign是什么?

FeignNetflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API
使用Feign非常简单—创建一个接口,并在接口上添加一些注解,代码就完成了。Feign具备可插拔的注解、支持多种注解,例如Feign自带的注解或者JAX-RS注解等
Spring Cloud Feign是基于Netflix feign实现,整合了Spring Cloud RibbonSpring Cloud Hystrix,除了提供这两者的强大功能外,还提供了一种声明式的Web服务客户端定义的方式
SpringCloud之OpenFeign_第2张图片
SpringCloud之OpenFeign_第3张图片
SpringCloud之OpenFeign_第4张图片
动手实践
(1)添加Feign依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.demo.cloud</groupId>
  <artifactId>microservice-consumer-movie-feign</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <!-- 引入spring boot的依赖 -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.3.RELEASE</version>
  </parent>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
    <!--添加feign依赖-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-feign</artifactId>
    </dependency>
  </dependencies>
  <!-- 引入spring cloud的依赖 -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Camden.SR4</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <!-- 添加spring-boot的maven插件 -->
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

(2)创建一个Feign接口,并添加@FeignClient注解

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
import com.demo.cloud.study.user.entity.User;
 
@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
}

(3)修改Controller代码,让其调用Feign接口

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
 
import com.demo.cloud.study.user.entity.User;
import com.demo.cloud.study.user.feign.UserFeignClient;
 
@RestController
public class MovieController {
  @Autowired
  private UserFeignClient userFeignClient;
 
  @GetMapping("/user/{id}")
  public User findById(@PathVariable Long id) {
    return this.userFeignClient.findById(id);
  }
}

(4)修改启动类,为其添加@EnableFeignClients注解
添加注解:@EnableFeignClients @EnableDiscoveryClient

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
 
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class ConsumerMovieApplication {
  public static void main(String[] args) {
    SpringApplication.run(ConsumerMovieApplication.class, args);
  }
}

2、OpenFeign是什么?

OpenFeign 是 SpringCloud在Feign 的基础上支持了SpringMVC的注解,如@RequestMapping等。OpenFeign 的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。

3、Feign和openFeign有什么区别?

Feign openFeign
FeignNetflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。使用Feign非常简单—创建一个接口,并在接口上添加一些注解,代码就完成了。Feign具备可插拔的注解、支持多种注解,例如Feign自带的注解或者JAX-RS注解等`。 OpenFeign 是 SpringCloud在Feign 的基础上支持了SpringMVC的注解,如@RequestMapping等。OpenFeign 的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类`,实现类中做负载均衡并调用其他服务。

4、OpenFeign服务调用

接口+注解:微服务调用接口 + @FeignClient

1. 新建 cloud-consumer-feign-order80
2. 添加依赖


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>LearnCloudartifactId>
        <groupId>com.lun.springcloudgroupId>
        <version>1.0.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>cloud-consumer-feign-order80artifactId>

    <dependencies>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
        
        <dependency>
            <groupId>com.lun.springcloudgroupId>
            <artifactId>cloud-api-commonsartifactId>
            <version>${project.version}version>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-devtoolsartifactId>
            <scope>runtimescope>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>
project>

3、添加 applicatin.yml 配置

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

4. 主启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
public class OrderFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderFeignMain80.class, args);
    }
}

5. 业务处理逻辑类

业务逻辑接口+@FeignClient配置调用provider服务

新建 PaymentFeignService 接口并新增注解@FeignClient

import com.lun.springcloud.entities.CommonResult;
import com.lun.springcloud.entities.Payment;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService
{
    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);

}
Controller 控制层
import com.lun.springcloud.entities.CommonResult;
import com.lun.springcloud.entities.Payment;
import com.lun.springcloud.service.PaymentFeignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
@Slf4j
public class OrderFeignController
{
    @Resource
    private PaymentFeignService paymentFeignService;

    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
    {
        return paymentFeignService.getPaymentById(id);
    }
}

5、openFeign如何传参?

开发中接口传参的方式有很多,在openFeign中的传参是有一定规则的,下面详细介绍。

1、传递JSON数据
Spring Boot 中通过@RequestBody标识入参。
@RestController
@RequestMapping("/openfeign/provider")
public class OpenFeignProviderController {
    @PostMapping("/order")
    public Order createOrder(@RequestBody Order order){
        return order;
    }
}
consumer中openFeign接口中传参代码如下:
@FeignClient(value = "openFeign-provider")
public interface OpenFeignService {
    /**
     * 参数默认是@RequestBody标注的,这里的@RequestBody可以不填
     * 方法名称任意
     */
    @PostMapping("/openfeign/provider/order")
    Order createOrder(@RequestBody Order order);
}

注意:openFeign默认的传参方式就是JSON传参(@RequestBody),因此定义接口的时候可以不用@RequestBody注解标注,不过为了规范,一般都填上。

2、POJO表单传参

openFeign提供了一个注解@SpringQueryMap完美解决POJO表单传参。

provider服务提供者代码如下:
@RestController
@RequestMapping("/openfeign/provider")
public class OpenFeignProviderController {
    @PostMapping("/order1")
    public Order createOrder1(Order order){
        return order;
    }
}
consumer消费者openFeign代码如下:
@FeignClient(value = "openFeign-provider")
public interface OpenFeignService {
    /**
     * 参数默认是@RequestBody标注的,如果通过POJO表单传参的,使用@SpringQueryMap标注
     */
    @PostMapping("/openfeign/provider/order1")
    Order createOrder1(@SpringQueryMap Order order);
}
3、URL中携带参数

此种方式针对restful方式中的GET请求,也是比较常用请求方式。

provider服务提供者代码如下:
@RestController
@RequestMapping("/openfeign/provider")
public class OpenFeignProviderController {

    @GetMapping("/test/{id}")
    public String test(@PathVariable("id")Integer id){
        return "accept one msg id="+id;
}
consumer消费者openFeign接口如下:
@FeignClient(value = "openFeign-provider")
public interface OpenFeignService {

    @GetMapping("/openfeign/provider/test/{id}")
    String get(@PathVariable("id")Integer id);
}
4、普通表单参数

此种方式传参不建议使用,但是也有很多开发在用。

provider服务提供者代码如下:
@RestController
@RequestMapping("/openfeign/provider")
public class OpenFeignProviderController {
    @PostMapping("/test2")
    public String test2(String id,String name){
        return MessageFormat.format("accept on msg id={0},name={1}",id,name);
    }
}
consumer消费者openFeign接口传参如下:
@FeignClient(value = "openFeign-provider")
public interface OpenFeignService {
    /**
     * 必须要@RequestParam注解标注,且value属性必须填上参数名
     * 方法参数名可以任意,但是@RequestParam注解中的value属性必须和provider中的参数名相同
     */
    @PostMapping("/openfeign/provider/test2")
    String test(@RequestParam("id") String arg1,@RequestParam("name") String arg2);
}

6、OpenFeign的超时处理

超时设置,故意设置超时演示出错情况
1.服务提供方8001/8002故意写暂停程序

@RestController
@Slf4j
public class PaymentController {
    
    ...
    
    @Value("${server.port}")
    private String serverPort;

    ...
    
    @GetMapping(value = "/payment/feign/timeout")
    public String paymentFeignTimeout()
    {
        // 业务逻辑处理正确,但是需要耗费3秒钟
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return serverPort;
    }
    
    ...
}

2.服务消费方80 添加超时方法 PaymentFeignService

CLOUD-PAYMENT-SERVICE 注册Eruka的服务名称

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService{

    ...

    @GetMapping(value = "/payment/feign/timeout")
    public String paymentFeignTimeout();
}


3.服务消费方80 添加超时方法 OrderFeignController

@RestController
@Slf4j
public class OrderFeignController
{
    @Resource
    private PaymentFeignService paymentFeignService;

    ...

    @GetMapping(value = "/consumer/payment/feign/timeout")
    public String paymentFeignTimeout()
    {
        // OpenFeign客户端一般默认等待1秒钟
        return paymentFeignService.paymentFeignTimeout();
    }
}

4、测试情况
多次刷新http://localhost/consumer/payment/feign/timeout
将会跳出错误Spring Boot默认错误页面,主要异常:feign.RetryableException:Read timed out executing GET http://CLOUD-PAYMENT-SERVCE/payment/feign/timeout。

openFeign 其实是有默认的超时时间的,默认分别是连接超时时间10秒、读超时时间60秒,源码在feign.Request.Options#Options()这个方法中,如下图
SpringCloud之OpenFeign_第5张图片
那么问题来了:为什么我只设置了 睡眠3秒 就报超时呢?
其实openFeign集成了Ribbon,Ribbon的默认超时连接时间、读超时时间都是是1秒,源码在org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer#execute()方法中,如下图:
SpringCloud之OpenFeign_第6张图片
源码逻辑: 如果openFeign没有设置对应得超时时间,那么将会采用Ribbon的默认超时时间。 理解了超时设置的原理,由之产生两种方案也是很明了了,如下: 设置openFeign的超时时间 设置Ribbon的超时时间
1、设置Ribbon的超时时间(不推荐)
设置很简单,在配置文件中添加如下设置:

ribbon:
  # 值的是建立链接所用的时间,适用于网络状况正常的情况下, 两端链接所用的时间
  ReadTimeout: 5000
  # 指的是建立链接后从服务器读取可用资源所用的时间
  ConectTimeout: 5000

2、设置openFeign的超时时间(推荐)
openFeign设置超时时间非常简单,只需要在配置文件中配置,如下:

default设置的是全局超时时间,对所有的openFeign接口服务都生效
feign:
  client:
    config:
      ## default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间
      default:
        connectTimeout: 5000
        readTimeout: 5000

注意:单个配置的超时时间将会覆盖全局配置。

feign:
  client:
    config:
      ## default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间
      default:
        connectTimeout: 5000
        readTimeout: 5000
      ## 为serviceC这个服务单独配置超时时间
      serviceC:
        connectTimeout: 30000
        readTimeout: 30000

7、OpenFeign如何替换默认的httpClient?

OpenFeign 底层通信组件默认使用 JDK 自带的 URLConnection 对象进行 HTTP 请求的,因为没有使用连接池,所以性能不是很好。我们可以将 OpenFeign 的通讯组件,手动替换成像 Apache HttpClient 或 OKHttp 这样的专用通信组件,这些的专用通信组件自带连接池可以更好地对 HTTP 连接对象进行重用与管理,同时也能大大的提升 HTTP 请求的效率。
接下来我以 Apache HttpClient 为例,演示一下专用通讯组件的使用。
1、引入Apache HttpClient依赖
在项目的依赖管理文件 pom.xml 中添加以下配置:


<dependency>
 <groupId>org.springframework.cloudgroupId>
 <artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

<dependency>
 <groupId>io.github.openfeigngroupId>
 <artifactId>feign-httpclientartifactId>
dependency>

为什么要添加上面的依赖呢?从源码中不难看出,请看org.springframework.cloud.openfeign.FeignAutoConfiguration.HttpClientFeignConfiguration这个类,代码如下:
SpringCloud之OpenFeign_第7张图片
上述红色框中的生成条件,其中的@ConditionalOnClass(ApacheHttpClient.class),必须要有ApacheHttpClient这个类才会生效并且feign.httpclient.enabled这个配置要设置为true

2、开启Apache HttpClient使用
启动 Apache HttpClient 组件,在项目配置文件 application.yml 中添加以下配置:

feign:
client:
 httpclient: # 开启 HttpClient
   enabled: true

3、如何验证已经替换成功?
feign.SynchronousMethodHandler#executeAndDecode()这个方法中可以清楚的看出调用哪个client,如下图:最终调用的是ApacheHttpClient
SpringCloud之OpenFeign_第8张图片

8、OpenFeign如何开启日志增强?

openFeign虽然提供了日志增强功能,但是默认是不显示任何日志的,不过开发者在调试阶段可以自己配置日志的级别。
openFeign的日志级别如下:

NONE默认的,不显示任何日志;
BASIC仅记录请求方法、URL、响应状态码及执行时间;
HEADERS除了BASIC中定义的信息之外,还有请求和响应的头信息;
FULL除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据。
配置起来也很简单,步骤如下:
1、配置日志bean
需要自定义一个配置类,在其中设置日志级别,如下:

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfig
{
    @Bean
    Logger.Level feignLoggerLevel()
    {
        return Logger.Level.FULL;
    }
}

2、YML文件里需要开启日志的Feign客户端

logging:
  level:
    # feign日志以什么级别监控哪个接口
    com.lun.springcloud.service.PaymentFeignService: debug

虽然 OpenFeign 默认是不输出任何日志,但在开发阶段可能会被修改,因此在生产环境中,我们应仔细检查并设置合理的日志级别,以提高 OpenFeign 的运行效率。

上述步骤将日志设置成了FULL此时发出请求,日志效果如下图
SpringCloud之OpenFeign_第9张图片

9、OpenFeign如何熔断降级?

常见的熔断降级框架有Hystrix、Sentinel,openFeign默认支持的就是Hystrix,这个在官方文档上就有体现。
阿里的Sentinel无论是功能特性、简单易上手等各方面都完全秒杀Hystrix,因此此章节就使用openFeign+Sentinel进行整合实现服务降级。
1、添加Sentinel依赖
在 openFeign-consumer 消费者的pom文件添加sentinel依赖(由于使用了聚合模块,不指定版本号),如下

<dependency>
      <groupId>com.alibaba.cloudgroupId>
      <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>

2、配置文件中开启sentinel熔断降级
要想openFeign使用sentinel的降级功能,还需要在配置文件中开启,添加如下配置

feign:
  sentinel:
    enabled: true

3、添加降级回调类
这个类一定要和openFeign接口实现同一个类,如下图:
在这里插入图片描述
OpenFeignFallbackService这个是降级回调的类,一旦OpenFeignService中对应得接口出现了异常则会调用这个类中对应得方法进行降级处理。
4、添加fallback属性
@FeignClient中添加fallback属性,属性值是降级回调的类,如下:

@FeignClient(value = "openFeign-provider",fallback = OpenFeignFallbackService.class)
public interface OpenFeignService {}

5、验证

注意:实际开发中返回结果应该根据架构统一定制,这里只是为了演示方便。

现在手动造个异常,在服务提供的接口中抛出异常,如下图
SpringCloud之OpenFeign_第10张图片
SpringCloud之OpenFeign_第11张图片

10、OpenFeign如何做通讯优化?

在讲如何优化之前先来看一下GZIP 压缩算法,概念如下

gzip是一种数据格式,采用用deflate算法压缩数据;gzip是一种流行的数据压缩算法,应用十分广泛,尤其是在Linux平台。

网络数据经过压缩后实际上降低了网络传输的字节数,最明显的好处就是可以加快网页加载的速度。网页加载速度加快的好处不言而喻,除了节省流量,改善用户的浏览体验外,另一个潜在的好处是GZIP与搜索引擎的抓取工具有着更好的关系。例如 Google就可以通过直接读取GZIP文件来比普通手工抓取更快地检索网页。
GZIP压缩传输的原理如下图
SpringCloud之OpenFeign_第12张图片
步骤拆解:

  • 客户端向服务器请求头中带有:Accept-Encoding:gzip,deflate
    字段,向服务器表示,客户端支持的压缩格式(gzip或者deflate),如果不发送该消息头,服务器是不会压缩的。
  • 服务端在收到请求之后,如果发现请求头中含有Accept-Encoding字段,并且支持该类型的压缩,就对响应报文压缩之后返回给客户端,并且携带
  • Content-Encoding:gzip消息头,表示响应报文是根据该格式压缩过的。
    客户端接收到响应之后,先判断是否有Content-Encoding消息头,如果有,按该格式解压报文。否则按正常报文处理。
    openFeign支持请求/响应开启GZIP压缩,整体的流程如下图:
    SpringCloud之OpenFeign_第13张图片
    上图中涉及到GZIP传输的只有两块,分别是Application client --> Application Service、 Application Service -->Application client。
    注意:openFeign支持的GZIP仅仅是在openFeign接口的请求和响应,即是openFeign消费者调用服务提供者的接口。
    openFeign开启GZIP步骤需要在配置文件中开启如下配置:
feign:
  ## 开启压缩
  compression:
    request:
      enabled: true
      ## 开启压缩的阈值,单位字节,默认2048,即是2k,这里为了演示效果设置成10字节
      min-request-size: 10
      mime-types: text/xml,application/xml,application/json
    response:
      enabled: true

上述发出请求后可以看到请求头中已经携带了GZIP压缩SpringCloud之OpenFeign_第14张图片
PS:如果服务消费端的 CPU 资源比较紧张的话,建议不要开启数据的压缩功能,因为数据压缩和解压都需要消耗 CPU 的资源,这样反而会给 CPU 增加了额外的负担,也会导致系统性能降低。

负载均衡优化

OpenFeign 底层使用的是 Ribbon 做负载均衡的,查看源码我们可以看到它默认的负载均衡策略是轮询策略,如下图所示:
SpringCloud之OpenFeign_第15张图片
轮询策略之外,我们还有其他 6 种内置的负载均衡策略可以选择,这些负载均衡策略如下:

权重策略:WeightedResponseTimeRule,根据每个服务提供者的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性也就越低。它的实现原理是,刚开始使用轮询策略并开启一个计时器,每一段时间收集一次所有服务提供者的平均响应时间,然后再给每个服务提供者附上一个权重,权重越高被选中的概率也越大。

最小连接数策略:BestAvailableRule,也叫最小并发数策略,它是遍历服务提供者列表,选取连接数最小的⼀个服务实例。如果有相同的最小连接数,那么会调用轮询策略进行选取。

区域敏感策略:ZoneAvoidanceRule,根据服务所在区域(zone)的性能和服务的可用性来选择服务实例,在没有区域的环境下,该策略和轮询策略类似。

可用敏感性策略:AvailabilityFilteringRule,先过滤掉非健康的服务实例,然后再选择连接数较小的服务实例。

随机策略:RandomRule,从服务提供者的列表中随机选择一个服务实例。

重试策略:RetryRule,按照轮询策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试来获取服务,如果超过指定时间依然没获取到服务实例则返回 null。

出于性能方面的考虑,我们可以选择用权重策略或区域敏感策略来替代轮询策略,因为这样的执行效率最高

你可能感兴趣的:(SpringCloud,spring,cloud,微服务)