学习目标

  • 负载均衡Ribbon
  • 声明式服务调用Feign

1.负载均衡Ribbon

1.1.什么是负载均衡

通俗的讲,负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。

nacos loadbalancer自定义负载均衡策略_负载均衡

1.2.自定义实现负载均衡

1.2.1.创建服务提供者

1.2.1.1.创建工程

拷贝nacos_provider:

nacos loadbalancer自定义负载均衡策略_java_02

1.2.1.2.application.yml
server:
  port: 9090
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.182.132:8848
  application:
    name: ribbon-provider
server:
  port: 9091
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.182.132:8848
  application:
    name: ribbon-provider

1.2.2.创建服务消费者

1.2.2.1.创建工程

拷贝nacos_consumer:

nacos loadbalancer自定义负载均衡策略_负载均衡_03

1.2.2.2.application.yml
server:
  port: 80
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.209.129:8848
  application:
    name: ribbon-consumer
1.2.2.3.controller
package com.bjpowernode.controller;

import com.bjpowernode.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Random;

/**
 * Created with IntelliJ IDEA.
 * 随机策略
 * @Author: TOM
 * @Date: 2022/10/09/17:21
 * @Description:
 */
@RestController
@RequestMapping("/consumer")
public class UserController {

    @Autowired
    private RestTemplate restTemplate;
    //springcloud提供的工具类,作用:发现服务
    @Autowired
    private DiscoveryClient discoveryClient;

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Integer id){

        //1、使用随机策略解决负载均衡的问题
        // 随机获取一个随机数,随机数的取值范围是获取服务集合中元素的个数
        List<ServiceInstance> instancesList = discoveryClient.getInstances("ribbon-provider");
        int currentIndex = new Random().nextInt(instancesList.size());
        //获取服务
        ServiceInstance service = instancesList.get(currentIndex);
        String url = "http://"+ service.getHost() +":"+ service.getPort() +"/provider/getUserById/"+id;
        return restTemplate.getForObject(url, User.class);
    }
}

1.2.3.测试

使用随机策略进行测试

nacos loadbalancer自定义负载均衡策略_spring_04


nacos loadbalancer自定义负载均衡策略_ribbon_05


随机访问provider使用轮询策略测试

nacos loadbalancer自定义负载均衡策略_ribbon_06

nacos loadbalancer自定义负载均衡策略_java_07

1.1.Ribbon介绍

1.1.1.什么是Ribbon

  • Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

nacos loadbalancer自定义负载均衡策略_java_08

  • 在nacos里面已经集成了ribbon的依赖:
  • Ribbon默认提供 很多种负载均衡算法,例如轮询、随机 等等。

1.1.2.负载均衡策略

负载均衡接口:com.netflix.loadbalancer.IRule

nacos loadbalancer自定义负载均衡策略_java_09

1.1.2.1.随机策略

com.netflix.loadbalancer.RandomRule:该策略实现了从服务清单中随机选择一个服务实例的功能。

nacos loadbalancer自定义负载均衡策略_java_10

1.1.2.2.轮询策略

com.netflix.loadbalancer.RoundRobinRule:该策略实现按照线性轮询的方式依次选择实例的功能。具体实现如下,在循环中增加了一个count计数变量,该变量会在每次轮询之后累加并求余服务总数

nacos loadbalancer自定义负载均衡策略_java_11

nacos loadbalancer自定义负载均衡策略_java_12

1.3.基于ribbon实现负载均衡

原理:在RestTemplate上添加@LoadBalanced后,ribbon会给RestTemplate的请求添加拦截器,在拦截器中根据serverId从nacos中获得List,然后再使用ribbon的负载均衡算法从List获得一个service,获得service的ip和端口 之后将"http://ribbon-provider/provider/getUserById/"中的ribbon-provider转换成ip和端口。

ribbon经过负载均衡算法,平均分配给你一个服务的ip和端口,之后用restTemplate进行调用

ribbon缺点:拼接url和参数显得好傻、不能剔除死亡节点

1.3.1.修改ribbon_consumer

1.3.1.1.ConfigBean
package com.bjpowernode.config;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;


@Configuration
public class BeanConfiger {

    //RestTemplate:是spring提供的一个工具类,作用是发送restful请求
    /**
     * 在RestTemplate上添加@LoadBalanced后,ribbon会给RestTemplate的请求添加拦截器
     * 在拦截器中根据serverId从nacos中获得List<Service>,然后再使用ribbon的负载均衡算法从		    List<Service>获得一个service
     * 获得service的ip和端口 之后将"http://ribbon-provider/provider/getUserById/"中的ribbon-provider转换成ip和端口
     */
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    //将负载均衡算法放入容器
    @Bean
    public IRule iRule(){
        return new RandomRule();
    }
}
1.3.1.2.controller
package com.bjpowernode.controller;

import com.bjpowernode.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Random;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: TOM
 * @Date: 2022/10/09/17:21
 * @Description:
 */
@RestController
@RequestMapping("/consumer")
public class UserController {

    @Autowired
    private RestTemplate restTemplate;
    //springcloud提供的工具类,作用:发现服务
    @Autowired
    private DiscoveryClient discoveryClient;

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Integer id){
		
		//将ip和端口改为nacos中的服务名
        String url = "http://ribbon-provider/provider/getUserById/"+id;
        return restTemplate.getForObject(url, User.class);
    }
}

1.3.2.测试

  1. 分别使用轮询和随机策略调用服务提供者

2.声明式服务调用Feign

2.1.背景

当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻

那么有没有更好的解决方案呢?答案是确定的有,Netflix已经为我们提供了一个框架:Feign。

2.2.Feign概述

Feign是Spring Cloud提供的声明式、模板化的HTTP客户端, 它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。

Spring Cloud集成Feign并对其进行了增强,使Feign支持了Spring MVC注解;Feign默认集成了Ribbon,所以Fegin默认就实现了负载均衡的效果。

说白了Feign就是RestTemplate + Ribbon,声明式是指先将要调用的服务中的controller中的方法声明出来,定义一个接口来声明,之后调用接口中的方法,就像调用本地的方法一样

2.3.Feign入门

nacos loadbalancer自定义负载均衡策略_java_13

2.3.1.创建服务提供者

2.3.1.1.创建工程
  • 拷贝ribbon_provider_1

nacos loadbalancer自定义负载均衡策略_ribbon_14

2.3.1.2.application.yml
server:
  port: 9092
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.209.129:8848
  application:
    name: feign-provider

2.3.2.创建feign接口

2.3.2.1.创建工程

nacos loadbalancer自定义负载均衡策略_负载均衡_15

2.3.2.2.pom.xml
<?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.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud_parent</artifactId>
        <groupId>com.bjpowernode</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>feign_interface</artifactId>

    <dependencies>
        <!--Spring Cloud OpenFeign Starter -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.bjpowernode</groupId>
            <artifactId>springcloud_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>
2.3.2.3.feign
package com.bjpowernode.feign;

import com.bjpowernode.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: TOM
 * @Date: 2022/10/11/18:38
 * @Description:
 */
@FeignClient("feign-provider")
@RequestMapping("/provider")
public interface UserFeign {
    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable("id") Integer id);
}

2.3.3.创建服务消费者

2.3.3.1.创建工程
  • 拷贝ribbon_consumer
2.3.3.2.pom.xml

nacos loadbalancer自定义负载均衡策略_负载均衡_16

<?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.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springcloud_parent</artifactId>
        <groupId>com.bjpowernode</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>ribbon_consumer</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.bjpowernode</groupId>
            <artifactId>springcloud_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--feign接口-->
        <dependency>
            <groupId>com.bjpowernode</groupId>
            <artifactId>feign_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>
2.3.3.3.application.yml
server:
  port: 80
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.182.132:8848
  application:
    name: feign-consumer
2.3.3.4.Controller
package com.bjpowernode.controller;

import com.bjpowernode.feign.UserFeign;
import com.bjpowernode.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


/**
 * Created with IntelliJ IDEA.
 *
 * @Author: TOM
 * @Date: 2022/10/09/17:21
 * @Description:
 */
@RestController
@RequestMapping("/consumer")
public class UserController {

    @Autowired
    private UserFeign userFeign;

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Integer id){
        return userFeign.getUserById(id);
    }
}
2.3.3.4.app
package com.bjpowernode;

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

@SpringBootApplication
@EnableDiscoveryClient
//@EnableFeignClients(basePackages = "com.bjpowernode.feign")
@EnableFeignClients//开启feign接口扫描
public class FeignConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(FeignConsumerApp.class,args);
    }
}

2.3.4.测试

nacos loadbalancer自定义负载均衡策略_java_17

2.4.Feign原理

2.4.1.FeignInvocationHandler实现 InvocationHandler

通过 JDK Proxy 生成动态代理类,核心步骤就是需要定制一个调用处理器,具体来说,就是实现JDK中位于java.lang.reflect 包中的 InvocationHandler 调用处理器接口,并且实现该接口的 invoke(…) 抽象方法。

为了创建Feign的远程接口的代理实现类,Feign提供了自己的一个默认的调用处理器,叫做 FeignInvocationHandler 类,该类处于 feign-core 核心jar包中。当然,调用处理器可以进行替换,如果Feign与Hystrix结合使用,则会替换成 HystrixInvocationHandler 调用处理器类,类处于 feign-hystrix 的jar包中。

默认的调用处理器 FeignInvocationHandler 是一个相对简单的类,有一个非常重要Map类型成员 dispatch 映射,保存着远程接口方法到MethodHandler方法处理器的映射。

nacos loadbalancer自定义负载均衡策略_负载均衡_18


默认的调用处理器 FeignInvocationHandle,在处理远程方法调用的时候,会根据Java反射的方法实例,在dispatch 映射对象中,找到对应的MethodHandler 方法处理器,然后交给MethodHandler 完成实际的HTTP请求和结果的处理。前面示例中的 DemoClient 远程调用接口,有两个远程调用方法,所以,其代理实现类的调用处理器 FeignInvocationHandler 的dispatch 成员,有两个有两个Key-Value键值对。

package feign;
//...省略import

public class ReflectiveFeign extends Feign {

  //...

  //内部类:默认的Feign调用处理器 FeignInvocationHandler
  static class FeignInvocationHandler implements InvocationHandler {

    private final Target target;
    //方法实例对象和方法处理器的映射
    private final Map<Method, MethodHandler> dispatch;

    //构造函数    
    FeignInvocationHandler(Target target, Map<Method, MethodHandler> dispatch) {
      this.target = checkNotNull(target, "target");
      this.dispatch = checkNotNull(dispatch, "dispatch for %s", target);
    }

    //默认Feign调用的处理
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      //...
	  //首先,根据方法实例,从方法实例对象和方法处理器的映射中,
	  //取得 方法处理器,然后,调用 方法处理器 的 invoke(...) 方法
         return dispatch.get(method).invoke(args);
    }
    //...
  }

源码很简单,重点在于invoke(…)方法,虽然核心代码只有一行,但是其功能是复杂的:

(1)根据Java反射的方法实例,在dispatch 映射对象中,找到对应的MethodHandler 方法处理器;

(2)调用MethodHandler方法处理器的 invoke(…) 方法,完成实际的HTTP请求和结果的处理。

2.4.2.方法处理器 MethodHandler

Feign的方法处理器 MethodHandler 是一个独立的接口,定义在 InvocationHandlerFactory 接口中,仅仅拥有一个invoke(…)方法,源码如下:

//定义在InvocationHandlerFactory接口中
public interface InvocationHandlerFactory {
  //…

 //方法处理器接口,仅仅拥有一个invoke(…)方法
  interface MethodHandler {
    //完成远程URL请求
    Object invoke(Object[] argv) throws Throwable;
  }
//...
}

MethodHandler 的invoke(…)方法,主要职责是完成实际远程URL请求,然后返回解码后的远程URL的响应结果。Feign提供了默认的 SynchronousMethodHandler 实现类,提供了基本的远程URL的同步请求处理。 SynchronousMethodHandler实现了MethodHandle,调用MethodHandler 的invoke(…)方法实际上是调用 SynchronousMethodHandler的hander方法。该方法会生成url模板创建RequestTemplate(url、requestMethod、body)

public Object invoke(Object[] argv) throws Throwable {
        //创建一个RequestTemplate
        RequestTemplate template = this.buildTemplateFromArgs.create(argv);
        Retryer retryer = this.retryer.clone();

        while(true) {
            try {
                //发出请求
                return this.executeAndDecode(template);
            } catch (RetryableException var8) {
                ... ... ...
            }
        }
    }
package feign;

public final class RequestTemplate implements Serializable {
    ... ... ... ... ... ...
    private UriTemplate uriTemplate;
    private HttpMethod method;
    private Body body;
    ... ... ... ... ... ...
}

2.4.3.发起请求

SynchronousMethodHandler.executeAndDecode():

通过RequestTemplate生成Request,然后把Request交给Client去处理,Client可以是JDK原生的URLConnection,Apache的HttpClient,也可以时OKhttp,最后Client结合Ribbon负载均衡发起服务调用。

Object executeAndDecode(RequestTemplate template) throws Throwable {
        //生成请求对象
        Request request = this.targetRequest(template);
        if (this.logLevel != Level.NONE) {
            this.logger.logRequest(this.metadata.configKey(), this.logLevel, request);
        }

        long start = System.nanoTime();

        Response response;
        try {
            //发起请求
            response = this.client.execute(request, this.options);
        } catch (IOException var15) {
            ... ... ...

            throw FeignException.errorExecuting(request, var15);
        }
 }

总之执行原理大致为

1、扫描feign接口生成代理类并交给spring容器管理
        @EnableFeignClients开启feign接口扫描:FeignClientsRegistrar.registerFeignClients()扫描被@FeignClient标识的接口生成代理类,在扫描接口时候解析注解信息获取ip和端口号,将接口中的方法存在dispath映射集合中,之后将代理对象交给spring的容器管理
2、根据接口上的注解创建RequestTemplate
        当controller调用feign代理类时,代理对象首先调用 FeignInvocationHandler的invoke方法,获取methodhandler,之后通过反射调用SynchronousMethodHandler.invoke()创建RequestTemplate(url、requestMethod、body)
3、发送请求
         接着通过RequestTemplate创建Request,然后client(HttpClient、OkHttp、URLConnection)使用Request发送请求

2.5.Feign参数传递

传参方式:

1、?传参 路径拼接传参
    @RequestParam("id")
    
2、restful传参 路径传参
    @PathVariable("id")
    
3、pojo传参 参数为对象
    @RequestBody

测试
1、拼接?号url 使用 @RequestParam

//consumer的controller
 @RequestMapping("/delUserById")
    public User delUserById(Integer id){
        return userFeign.delUserById(id);
    }
    
    
  //feign接口
 @RequestMapping("/delUserById")
    User delUserById(@RequestParam Integer id);
    
    
//provider的controller
@RequestMapping("/delUserById")
    public User delUserById(Integer id){
        return userService.delUserById(id);

nacos loadbalancer自定义负载均衡策略_ribbon_19


2、传参为pojo

//consumer的controller
@RequestMapping("/addUser")
    public User addUser(User user){
        return userFeign.addUser(user);
    }
    
    
  //feign接口
 @RequestMapping("/addUser")
    User addUser(@RequestBody User user);
    
    
//provider的controller
@RequestMapping("/addUser")
    public User addUser(@RequestBody User user){
        return userService.addUser(user);
    }

nacos loadbalancer自定义负载均衡策略_负载均衡_20


3、传参为数组,实质也是路径拼接传参

//consumer的controller
@RequestMapping("/delUserByIds")
    public Integer[] delUserByIds(Integer[] ids){
        return userFeign.delUserByIds(ids);
    }
    
    
  //feign接口
 @RequestMapping("/delUserByIds")
    Integer[] delUserByIds(@RequestParam("ids") Integer[] ids);
    
    
//provider的controller
@RequestMapping("/delUserByIds")
    public Integer[] delUserByIds(Integer[] ids){
        return userService.delUserByIds(ids);
    }

nacos loadbalancer自定义负载均衡策略_ribbon_21


4、传参方式为集合,实质也是pojo

//consumer的controller
@RequestMapping("/addUsers")
    public List<User> addUsers(){
        List<User> userList = new ArrayList<>();
        userList.add(new User(1, "ZHAOLIU", 18));
        userList.add(new User(1, "LIQI", 17));
        userList.add(new User(1, "SONGBBA", 16));
        return userFeign.addUsers(userList);
    }
    
    
  //feign接口
 @RequestMapping("/addUsers")
    List<User> addUsers(@RequestBody List<User> userList);
    
    
//provider的controller
@RequestMapping("/addUsers")
    public List<User> addUsers(@RequestBody List<User> userList){
        return userService.addUsers(userList);
    }

nacos loadbalancer自定义负载均衡策略_ribbon_22

2.6.Feign优化

2.6.1.添加feign日志

feign:
  client:
    config:
      default: #这里default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        LoggerLevel: FULL #feign日志
logging:
	level:
		com.bjpowernode.feign: debug #log4j的日志级别

2.6.2 连接优化

Feign底层的客户端实现:

URLConnection:默认实现,不支持连接池
Apache HttpClient:支持连接池
OKHttp:支持连接池

优化方向:

使用连接池代替默认的URLConncetion
日志级别,最好用baseic或none

添加httpclient依赖

<dependency>
           	 <groupId>io.github.openfeign</groupId>
           	 <artifactId>feign-httpclient</artifactId>
</dependency>

切换http客户端成功

nacos loadbalancer自定义负载均衡策略_负载均衡_23

2.6.2 通讯优化

2.6.2.1 GZIP简介

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

gzip能力:
当Gzip压缩到一个纯文本数据时,效果是非常明显的,大约可以减少70%以上的数据大小。

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

2.6.2.2 HTTP协议中关于压缩传输的规定(原理)

nacos loadbalancer自定义负载均衡策略_负载均衡_24


第一:

客户端向服务器请求头中带有:Accept-Encoding:gzip, deflate 字段,向服务器表示,客户端支持的压缩格式(gzip或者deflate),如果不发送该消息头,服务器是不会压缩的。

第二:
服务端在收到请求之后,如果发现请求头中含有Accept-Encoding字段,并且支持该类型的压缩,就对响应报文压缩之后返回给客户端,并且携带Content-Encoding:gzip消息头,表示响应报文是根据该格式压缩过的。

第三:
客户端接收到响应之后,先判断是否有Content-Encoding消息头,如果有,按该格式解压报文。否则按正常报文处理。

2.6.2.3 在Feign技术中应用GZIP压缩

3.在Feign技术中应用GZIP压缩
在Spring Cloud微服务体系中,一次请求的完整流程如下:

nacos loadbalancer自定义负载均衡策略_1024程序员节_25

在整体流程中,如果使用GZIP压缩来传输数据,涉及到两次请求-应答。而这两次请求-应答的连接点是Application Client,那么我们需要在Application Client中配置开启GZIP压缩,来实现压缩数据传输。

2.6.2.4 只配置Feign请求-应答的GZIP压缩

在交互数据量级不够的时候,看不到压缩内容。
这里只开启Feign请求-应答过程中的GZIP,也就是浏览器-Application Client之间的请求应答不开启GZIP压缩。
在全局配置文件中,使用下述配置来实现Feign请求-应答的GZIP压缩

server:
  port: 80
  compression:
    enabled: true #开启浏览器<----->consumer的gzip压缩
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.182.132:8848 #注册中心的地址
  application:
    name: feign-consumer
feign:
  client:
    config:
      default: #这里default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        LoggerLevel: full
  compression:
      request:
        enabled: true #开启feign<---->provider的gzip压缩
        min-request-size: 2048
      response:
        enabled: true
logging:
  level:
    com.bjpowernode.feign: debug #log4j的日志级别
@Service
public class UserServiceImpl implements UserService {

	@Override
	public User getUser() {
        //模拟网络延迟
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return new User(1,"王粪堆",18);
	}
}
2.6.2.5 超时优化

模拟服务

@Service
public class UserServiceImpl implements UserService {

	@Override
    public List<User> addUsers(List<User> userList) {
        try {
            //模拟业务处理时间
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return userList;
    }
}

设置超时时间
使用ribbon设置

ribbon:
  ConnectTimeout: 5000 #请求连接的超时时间
  ReadTimeout: 1000 #请求处理的超时时间

使用feign设置

feign:
  client:
    config:
      feign-provider:
        ConnectionTimeout: 5000 #请求连接的超时时间
        ReadTimeout: 5000 #请求处理的超时时间

测试

nacos loadbalancer自定义负载均衡策略_负载均衡_26


不优化超时时间则报错,默认一秒

优化超时时间

feign:
  client:
    config:
      feign-provider:
        ConnectionTimeout: 5000 #请求连接的超时时间
        ReadTimeout: 5000 #请求处理的超时时间

nacos loadbalancer自定义负载均衡策略_spring_27


完美运行!