【SpringCloud】3.OpenFeign——服务注册与负载均衡

基本介绍

之前学了LoadBalance,已经能实现负载均衡了,为什么还需要学习OpoenFeign。简单的说:LoadBalancer能做的事情,OpenFeign都能做,LoadBalance不能做的事情,OpenFeign也能做。

基本介绍

OpenFeign,主要用于负载均衡,是一个声明式的Web服务客户端,从而使WEB服务的调用变得很简单。同时OpenFeign还有一些高级特性,例如超发控制、重试机制、默认HttpClient修改,请求响应压缩、OpenFeign日志打印。OpenFeign已经是当前微服务调用最常用的技术

能做什么

我们在使用LoadBalancer+RestTemplate实现了微服务的负载均衡调用,但是在实际开发中,一个接口往往会被多处调用,这就需要多次定义重复的代码,而OpenFeign简化了这个过程 。而且也可集成阿里巴巴的Sentinel来提供熔断、降级功能。通过OpenFeign只需要定义服务绑定接口且以声明式的方法,就能够优雅而且简单的实现服务调用。

OpenFeign通用步骤

前面我们已经学习了loadBlancer的引用,https://www.cnblogs.com/luyj00436/p/18580829。OpenFeign使用的原理如下:
image

接下来使用OpenFeign,为了区别LoadBalancer引用,这里新建了一个订单子工程。
image

引入OpenFeign和LoadBalancer的依赖

订单子工程引入OpenFeign和LoadBalancer的依赖。

 <!-- openFeign-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

启动类上加上@EnableFeignClients注解

订单子工程(服务引用端),在启动类上添加注解``启动OPenFeignClient功能。

@SpringBootApplication
@EnableDiscoveryClient  // 向consul注册中心时提供服务
@EnableFeignClients(basePackages = "com.atguigu.cloud") //如果FeignClient不在SpringBootApplication的扫描范围内可以在@EnableFeignClients中指定扫描范围
public class MainFeign80 {
    public static void main(String[] args) {
        SpringApplication.run(MainFeign80.class, args);
    }
}

在项目通用方法中api包,并保存api接口

在通用方法中,也引入OpenFeign的依赖。

 <!-- openFeign-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

新建支付模块接口
image

支付模块中,添加@FeignClient注解,注解的值就是被调用的微服务方法。编写接口中方法,方法上的注解就是别调用方法的请求类型和地址。返回值需要和被调用接口返回值一致。

@FeignClient(value = "cloud-payment-service")
public interface PayFeignApi {
    /**
     * 新增订单
     * @return
     */
    @PostMapping("/pay/add")
    public ResultData<String> addPay();

    /**
     * 根据Id删除订单
     * @param id
     * @return
     */
    @DeleteMapping("/pay/del/{id}")
    public ResultData<Integer> deletePay(@PathVariable("id") Integer id);

    /**
     * 更新订单信息
     * @param payDTO
     * @return
     */
    @PutMapping("/pay/update")
    public  ResultData<String> updatePay(@RequestBody PayDTO payDTO);

    /**
     * 根据Id获取订单信息
     * @param id
     * @return
     */
    @GetMapping("/pay/get/{id}")
    public ResultData<Pay> getById(@RequestParam("id") Integer id);

    /**
     * 获取所有的订单信息
     * @return
     */
    @GetMapping("/pay/gets")
    public ResultData<List> getPayList();

    /**
     * 获取端口号
     * @param request
     * @return
     */
    @GetMapping("/pay/get/port")
    public ResultData<String> getPort();
}

调用微服务模块(支付模块,cloud-openfeign-order80)调佣feign接口方法

打开支付模块,新建调用方feign方法。

// 注入feign对象
@Resource
private PayFeignApi payFeignApi;

image
测试后,发现能够成功调用微服务。

OpenFeign的高级特性

前面已经完成了业务模块的基础使用。接下来,学习一些OpenFeign的高级特性,以应对微服务调用时的一些复操作。

OpenFeign超时控制

OpenFeign客户端的默认等待时间60S,超过这个时间就会报错

如果业务代码比较复杂或者网络原因,有可能出现超时。我们可以设置默认的超时时间。分为两种设置方式全局配置指定设置。指定设置优先级高于全局设置。

全局设置

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
          #指定超时时间最大:3S
            read-timeout: 3000
            #指定连接时间最大:3S
            connect-timeout: 3000

指定设置

spring:
  cloud:
    openfeign:
      client:
        config:
        #这里将default换成微服务的名称
          cloud-payment-service:
          #指定超时时间最大:3S
            read-timeout: 3000
            #指定连接时间最大:3S
            connect-timeout: 3000

注:可以修改被调用的支付模块等待时间,验证超时控制时间。

try {
    TimeUnit.SECONDS.sleep(62);	// 设置等待62s
}catch (InterruptedException e){
    e.printStackTrace();
}

此时,超时报错如下:
image

OpenFeign重试机制

默认情况下,超时连接会返回一个错。如果我们希望重新尝试连接呢?

重试机制默认时关闭的,我们只需要编写一个配置类,配置Retryer对象。

添加OpenFeign的配置类,设置重试机制

@Configuration
public class FeignConfig {
    @Bean
    public Retryer retryer(){
        // Retryer.Default( long period, long maxPeriod, int maxAttempts)
        // period : 多长时间后开启重试机制,这里设置100ms
        // maxPeriod : 重试间隔,这里设置1s一次
        // maxAttempts : 最大请求次数,这里设置3次
        return new Retryer.Default(100,1,3);
    }
}

运行测试重试:
image
image

前面配置时,设置等待时间3s。3次重试,开始时间和结束时间的时间差为9s。没有3次重试的过程,需要后续开启日志打印才可以看到。

OpenFeign默认HttpClient修改

为什么要修改HttpClient呢?

OpenFeign中的HttpClient默认采用的是JDK自带的HttpUrlConection发送HTTP请求。由于JDK的HttpUrlConection没有连接池,性能和效率上相对较低。

例如当我们遇到连接超时的错误时,也能看到是HttpURLConnection抛出的异常~这也能进一步证明默认采用的是HttpURLConnection
image

因此实际开发中,切换成Apache HttpClient 5是很有必要的。

步骤如下:1. 引入依赖;2. 开启配置说明

引入依赖

<!-- apche HttpClient的引用-->
<dependency>
	<groupId>org.apache.httpcomponents.client5</groupId>
	<artifactId>httpclient5</artifactId>
	<version>5.2.1</version>
</dependency>
<dependency>
	<groupId>io.github.openfeign</groupId>
	<artifactId>feign-hc5</artifactId>
	<version>13.3</version>
</dependency>

开启配置(yml文件为例)

feign:
  httpclient:
    hc5:
      enabled: true # 这是2.x的写法
# --------------- 以下是SpringBoot 3.0 写法 ---------------
spring:
  cloud:
    openfeign:
      httpclient:
        hc5:
          enabled: true

此时,测试超时报错,已经全部是HttpClient 5

1733366949341

OpenFeign请求/响应压缩

OpenFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗

spring:
  cloud:
    openfeign:
      compression:
        request:
        #开启请求压缩
          enabled: true
          #达到多大才触发压缩
          min-request-size: 2048
          #触发压缩的类型
          mime-types: types=text/xml,application/xml,application/json
        response:
          #开启响应压缩
          enabled: true

OpenFeign日志打印功能

OpenFeign需要输出日志需要符合两个条件:

  1. FeignClient所在的包日志级别为debug
  2. Feign的日志级别在NONE以上

Feign的日志级别:
NONE:不记录任何日志信息,这是默认值。
BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

步骤:定义一个类定义Feign的日志级别

public class DefaultFeignConfig {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.FULL;//日志级别
    }
}

配置文件中设置feign所在包的打印级别

logging:
  level:
  #下面是feign接口的包
    com:
      atguigu:
        cloud:
          apis:
            PayFeignApi: debug 

日志开启后,可以看到N次请求。
image

所谓念念不忘,必有回响。但……如果调用的服务器一直不能给我们回应,一直请求也不是个事儿,否则成了dos攻击了。这时候需要接受服务降级了。后续学到阿里巴巴的Sentinel,可以结合起来使用。

OpenFeign和Sentinel能够实现服务降级

之前学了LoadBalance

posted @ 2024-12-05 11:09  陆陆无为而治者  阅读(79)  评论(0编辑  收藏  举报