Ribbon与Feign的入门使用

问题描述

1. 负载均衡Ribbon

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

在这里插入图片描述

负载均衡策略

  • 随机策略:该策略实现了从服务清单中随机选择一个服务实例的功能。
  • 轮训策略:该策略实现按照线性轮询的方式依次选择实例的功能。

基于基于ribbon实现负载均衡

  • 开启ribbon负载均衡,注解@LoadBalanced

    @Configuration
    		public class ConfigBean {
    			@Bean
          /**
    	 * 添加了@LoadBalanced注解之后,Ribbon会给restTemplate请求添加一个拦截器,在拦截器中获取
    	 * 注册中心的所有可用服务,通过获取到的服务信息(ip,port)替换 serviceId 实现负载请求。
    	 */
    			@LoadBalanced //开启负载均衡,默认是轮询策略
    			public RestTemplate getRestTemplate(){
    				return new RestTemplate();
    			}//指定随机策略
    		@Bean
    		public IRule iRule() {
    			return new RandomRule();
    		}
    
  • 发送请求,借助RestTemplate对象发送请求,请求路径不再是ip+端口号,而是在nacos注册的服务名

    String serviceUrl = "ribbon-provider";
    return restTemplate.getForObject("http://" + serviceUrl + "/provider/getUserById/" + id, User.class);
    

ribbon的问题

拼接url和参数,是一种硬编码的方式。为了解决把请求路径硬编码的问题,我们推荐使用Feign声明式调用服务

2.声明式服务调用Feign

什么是feign

在这里插入图片描述

  • Feign是Spring Cloud提供的声明式、模板化的HTTP客户端,工作在consumer端
  • feign支持springmvc注解
  • feign集成了Ribbon也支持负载均衡
  • (ribbon+restTemplate)+优化=feign

feign依赖:spring-cloud-starter-openfeign

feign 的入门使用

消费者通过feign接口来调用某一个服务,需要三个模块,服务消费者,服务提供者,feign接口

  1. 创建provider,即服务提供者

    RestController
    @RequestMapping("/provider")
    public class ProviderController {
    
        @Autowired
        private UserService userService;
    
        @RequestMapping("/getUserById/{id}")
        public User getUserById(@PathVariable Integer id){
            return userService.getUserById(id);
        }
    }
    
    
  2. 创建feign_interface工程,注意feign接口必须在名为feign的包下

    • 引入openfeign依赖

    • feign接口,@FeignClient注解里的值为在nacos中注册的服务名,即要调用的服务;接口的方法名和所有注解要和调用的服务的方法保持一致

      @FeignClient("服务名")
      public interface UserFeign{
        @RequestMapping("/getUserById/{id}")
        User getUserById(@PathVariable("id") Integer Id); 
      }
      
  3. 创建consumer,即服务消费者

    • 依赖引入feign_interface

    • controller层,注入UserFeign的代理类,直接使用UserFeign代理类调用所需的服务

      @RestController
      @RequestMapping(value = "/consumer")
      public class ConsumerController {
        @Autowired
        private UserFeign userFeign;
        
        @RequestMapping("getUserById/{id}")
          public User getUserById(@PathVariable Integer id){
             return userFeign.getUserById(id);
          }
      }
      
    • application启动类上,添加@EnableFeignClients注解,表示开启feign注解扫描

feign接口的三种传参方式

  • 键值对传参或者路径?拼接传参

    参数前加@RequestParam(“id”),注解的值必须写明

  • restful风格传参,即路径传参

    参数前加@PathVariable(“id”),注解的值必须写明

  • pojo传参,即前端传json串之后json转换工具转换成java对象,包括实体对象、数组、集合等

    参数前加@RequestBody

feign原理

  1. 将feign接口的代理类扫描到Spring容器中:
    @EnableFeignClients开启feign注解扫描:FeignClientsRegistrar.registerFeignClients()扫描被 @FeignClient标识的接口生成代理类,并把接口和代理类交给Spring的容器管理。
  2. 为接口的方法创建RequestTemplate,当consumer调用feign代理类时,代理类会调用SynchronousMethodHandler.invoke()创建RequestTemplate(url,参数)
  3. 发出请求:
    代理类会通过RequestTemplate创建Request,然后client(URLConnetct、HttpClient、OkHttp)使用Request发送请求

feign优化

开启feign日志

feign日志默认有四种输出级别:NONE,BASIC,HEADERS,FULL

  • NONE:没有日志记录

  • BASIC:记录请求方法、URL以及响应状态代码和执行时间(一般使用这个)

  • HEADERS:记录基本信息以及请求和响应头信息

  • FULL:记录基本信息以及请求和响应头信息、请求和响应体信息

  • 特别提醒:在为某一个FeignClient文件设置日志记录级别的时候,一定要先设置好日志级别,推荐日志级别设置为DEBUG

	# feign配置
	feign:
		client:
		  config:
		    default: #default默认所有服务,也可以写要调用的服务名称
			    loggerLevel: full
	logging: 
		level:
		  com.bjpowernode.feign: debug #配置feign所在包的日志级别

feign超时

## 方法一:设置在ribbon上
ribbon:
  OkToRetryOnAllOperations: false #对所有操作请求都进行重试,默认false
  ReadTimeout: 5000   #负载均衡超时时间,默认值5000
  ConnectTimeout: 3000 #ribbon请求连接的超时时间,默认值2000
  MaxAutoRetries: 0     #对当前实例的重试次数,默认0
  MaxAutoRetriesNextServer: 1 #对切换实例的重试次数,默认1

## 方法二:设置在feign client上
feign:
  client:
    config:
      default:
        connectTimeout: 5000 #请求连接的超时时间
        readTimeout: 3000 #请求处理的超时时间

http连接池

feign的Http客户端支持3中框架,HttpURLConnection,HttpClient,OkHttp

两台服务器建立HTTP连接的过程涉及到多个数据包的交换,因为Feign默认采用的是传统JDK中的java.net.HttpURLConnection,每次请求都会建立,关闭连接,Http 连接需要的 3 次握手 4 次分手开销很大,很消耗时间。

所以我们需要更换http通信框架来节约大量的时间提示吞吐量,把它换成HttpClient作为底层通信框架。HttpClient 相比传统 JDK 自带的 HttpURLConnection,它封装了访问 http 的请求头,参数,内容体,响应等等;它不仅使客户端发送 HTTP 请求变得容易,而且也方便了开发人员测试接口(基于 Http 协议的),即提高了开发的效率,也方便提高代码的健壮性;另外高并发大量的请求网络的时候,还是用“连接池”提升吞吐量。

  • 解决办法:添加依赖

    <dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-httpclient</artifactId>
    </dependency>
    
  • 配置文件中开启

    feign:
    	httpclient: #开启httpclient
    		enabled: true
    

gzip压缩

  • 为什么要开启gzip压缩:

    我们压缩文件的目的就是为了把传输文件的体积减小,加快传输速度。我们在 http 传输中开启 gZip 的目的也是如此,我们写的代码(css,js)之类的文件会有很好的压缩效果,但是图片之类文件则不会被 gzip 压缩太多,因为它们已经内置了一些压缩。

  • feign的gzip压缩配置

    ### Feign 配置
    feign:
      compression:
        request:
          # 开启请求压缩
          enabled: true
          # 配置压缩的 MIME TYPE(这项默认压缩所有它认定的文件类型,可以不写)
          mime-types: text/xml,application/xml,application/json
          # 配置压缩数据大小的下限
          min-request-size: 2048
    

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)