3.OpenFeign与负载均衡

文章目录

前面消费者对于微服务的消费是通过 RestTemplate 完成的,这种方式的弊端是很明显的:消费者对提供者的调用无法与业务接口完全吻合。

例如,原本Service 接口中的方法是有返回值的,但经过 RestTemplate 相关API调用后没有了其返回值,最终执行是否成功用户并不清楚。

再例如 RestTemplate 的对数据的删除与修改操作方法都没有返回值。

代码编写不方便,不直观。提供者原本是按照业务接口提供服务的,而经过 RestTemplate一转手,变为了 URL,使得程序员在编写消费者对提供者的调用代码时,变得不直接、不明了。没有直接通过业务接口调用方便、清晰。

什么是 OpenFegin

  • 声明式 REST 客户端:Feign 通过使用 JAX-RS(JavaApieXtensionsofRESTful webServivces)或 SpringMVc 注解的修饰方式,生成接口的动态实现。"
  • Feign,假装、伪装。openFeign 可以将提供者提供的 Restful服务伪装为接口进行消费,消费者只需使用"feign 接口 + 注解"的方式即可直接调用提供者提供的 Restful 服务而无需再使用 RestTemplate。
  • 对于 openFeign,可简单总结为以下几点:OpenFeign 只涉及 Consumer,与Provider 无关。因为其是用于 Consumer 调用 Provider的
    • OpenFeign 仅仅就是一个伪客户端,其不会对请求做任务的处理。
    • OpenFeign 是通过注解的方式实现 RESTful 请求的。

0penFeign 与 Ribbon.

OpenFeign 具有负载均衡功能,其可以对指定的微服务采用负载均衡方式进行消费、访问。之前老版本 Springcloud 所集成的 OpenFeign 默认采用了 Ribbon 负载均衡器。但由于Netflix 已不再维护 Ribbon,所以从 Springcloud2021.x开始集成的 OpenFeign 中已彻底丢弃Ribbon,而是采用 SpringCloud 自行研发的 SpringCloud Loadbalancer 作为负载均衡器

对 consumer 的改造

  • SpringCloud 2021.x 版本不在使用 Ribbon,需要额外引入 SpringCloud-Loadbalancer 依赖
xml 复制代码
<!--openfegin依赖-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 新增 service 接口
java 复制代码
/**
 * ProjectName:    springcloudalibaba
 * ClassName:    DepartService
 * Package:    com.cheese.service
 * Description: openFegin 伪客户端接口
 * Datetime:    2024-07-23   1:12
 * Author:   LJZ
 */
@FeignClient(value = "depart-provider", path = "/provider/depart") //微服务名称,uri
public interface DepartService {
 /**
  * 接口名,注解路径,所有方法名与provider-server 中的接口一致
  * @param depart
  * @return
  */
    //新增
    @PostMapping("/save")
    Boolean addDepart(@RequestBody DepartEntity depart);

    //修改
    @PutMapping("/update")
    Boolean updateDepart(@RequestBody DepartEntity depart);

    //删除
    @DeleteMapping("/del/{id}")
    Boolean deleteDepartById(@PathVariable Integer id);

    //查询
    @GetMapping("/get/{id}")
    DepartEntity getDepartById(@PathVariable Integer id);

    //列表
    @GetMapping("/list")
    List<DepartEntity> getAllDepart();
}
java 复制代码
//SpringCloud2021.x前后版本的openfegin使用差异
//旧版本
@FeignClient(value = "depart-provider", path = "/provider/depart") //微服务名称,uri
或是
@FeignClient(value = "depart-provider") //微服务名称,uri
@RequestMapping("/provider/depart")
//两种方式均可
//-----------------------------------------
//新版本只能使用第一种方式进行注解配置
  • DepartController 中调用的 service 与接口方法命保持一致
java 复制代码
    @Resource
    private DepartService departService;

    //新增
    @PostMapping("/")
    public Boolean addDepart(@RequestBody DepartEntity depart) {
        return departService.addDepart(depart);
    }

    //修改
    @PutMapping("/")
    public Boolean modifyDepart(@RequestBody DepartEntity depart) {
        return departService.updateDepart(depart);
    }

    //删除
    @DeleteMapping("/{id}")
    public Boolean deleteDepart(@PathVariable Integer id) {
        return departService.deleteDepartById(id);
    }
    //查询
    @GetMapping("/{id}")
    public DepartEntity getDepart(@PathVariable Integer id) {
        return departService.getDepartById(id);
    }
    //列表
    @GetMapping("/list")
    public List<DepartEntity> getDepartList() {
       return departService.getAllDepart();
    }
  • 启动类上新增注解@EnableFeignClients //开启OpenFeginClient
  • 启动 nacos, 启动 consumer 启动 provider,使用 consumer,openfegin 调用 provider


超时配置

  • 在 consumer 的 yaml 配置文件中做如下配置
yaml 复制代码
spring:
  cloud:
        # OpenFegin 超时配置
    openfeign:
      client:
        config:
          default: #全局设置
            #consumer与provider建立连接的超时时间<==取决于网络因素
            connect-timeout: 1
            #建立连接后的读取时间,consumer发出请求到provider的响应这段时间的阈值<==取决于provider的业务逻辑
            read-timeout: 1
          depart-provider: #指定微服务设置,优先于全局设置,feginName即,@FeginClient注解value的值
            connect-timeout: 1
            read-timeout: 2
  • 使用全局设置时(将下方的 depart-provider 进行注释),重启 consumer,预期结果超时时间 1ms 出现 timeout 现象较多



  • 指定 feginName 方式(将注解放开),重启 consumer
  • 有时能够访问到,由于 read-timeout 比原先的的 default 设置的比较大,符合预期

请求响应的压缩设置

yaml 复制代码
spring:
  cloud:
    #对请求响应的压缩设置
    compression:
      request:
        #开启压缩配置
        enabled: true
        #指定类型
        mime-types: ["text/xml", "application/xml", "application/json","video/mp4"]
        #最小请求大小,默认值2048
        min-request-size: 1024
      response:
        enabled: true

选择远程调用的底层实现技术

  • feign 的远程调用底层实现技术默认采用的是 JDK的 URLConnection,同时还支持HttpClient 与OkHttp。.
  • 由于 JDK 的 URLConnection 不支持连接池,通信效率很低,所以生产中是不会使用该默认实现的。所以在 Spring cloud OpenFeign 中直接将默认实现变为了 Htpclient,同时也支持OkHttp。
  • 用户可根据业务需求选择要使用的远程调用底层实现技术。"

OpenFegin 整合 LoadBalancer 负载均衡

  • 紧接上文,现在已经有了一个 provider8081,如何使用 springcloud 负载均衡呢?查阅官网
  • 简而言之,想要使用 OpenFegin 客户端负载均衡,必须引入spring-cloud-starter-loadbalancer依赖,如果不引入依赖也能够使用默认的 feginclient,但是就不会有负载均衡的功能
  • 引入依赖
xml 复制代码
<!--nacos2.2.0.1往后版本的客户端负载均衡依赖-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
  • 使用 idea 动态参数构建 provider8082,provider8083


  • 可以看到 consumer 已经具备负载均衡功能了,默认负载均衡策略为轮询方式

负载均衡策略的更换

  • 新增一个配置类 DepartConfig.java,用于配置负载均衡策略
java 复制代码
/**
 * ProjectName:    springcloudalibaba
 * ClassName:    DepartConfig
 * Package:    com.cheese.config
 * Description: 用于修改负载均衡策略
 * Datetime:    2024-07-30   1:21
 * Author:   LJZ
 */
public class DepartConfig {
    @Bean
    public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                                   LoadBalancerClientFactory factory) {
        //获取负载均衡客户端名称,即提供者服务名称
        String serverName = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        //获取提供者微服务名称可用的实例列表
        ObjectProvider<ServiceInstanceListSupplier> lazyProvider = factory.getLazyProvider(serverName, ServiceInstanceListSupplier.class);
        //从集合lazyProvider中获取指定serverName的实例,随机做负载均衡
        return new RandomLoadBalancer(lazyProvider, serverName);
    }
}
  • 在 DepartConfig 类中未见@Configuration注解,在启动类中需添加@LoadBalancerClients(defaultConfiguration = DepartConfig.class)
  • 重启 consumer8080

小结

spring-cloud-loadbalancer 存在以下弊端

  • 负载均衡策略较少
    • 仅支持轮询和随机策略,默认是轮询策略
  • 更换负载均衡策略方式较为麻烦
  • 生产环境下使用的负载均衡器,通常是 dubbo
    • dubbo 作为通讯客户端,负载均衡策略可供选择更加多样
    • 无论是 openfegin 还是 resttemplate 建立通讯方式均是基于 http 协议进行
    • http 协议效率较低,生产环境下使用远程过程调用协议 RPC 效率会更高
    • 基于 RPC 通讯协议的框架恰好就有dubbo,此外还有 gRPC

相关推荐
川石课堂软件测试几秒前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
七星静香17 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员18 分钟前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU18 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie621 分钟前
在IDEA中使用Git
java·git
Elaine20239137 分钟前
06 网络编程基础
java·网络
G丶AEOM38 分钟前
分布式——BASE理论
java·分布式·八股
落落鱼201339 分钟前
tp接口 入口文件 500 错误原因
java·开发语言
想要打 Acm 的小周同学呀40 分钟前
LRU缓存算法
java·算法·缓存
镰刀出海43 分钟前
Recyclerview缓存原理
java·开发语言·缓存·recyclerview·android面试