【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使用的原理如下:
接下来使用OpenFeign,为了区别LoadBalancer引用,这里新建了一个订单子工程。
引入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>
新建支付模块接口
支付模块中,添加@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;
测试后,发现能够成功调用微服务。
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();
}
此时,超时报错如下:
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);
}
}
运行测试重试:
前面配置时,设置等待时间3s。3次重试,开始时间和结束时间的时间差为9s。没有3次重试的过程,需要后续开启日志打印才可以看到。
OpenFeign默认HttpClient修改
为什么要修改HttpClient呢?
OpenFeign中的HttpClient默认采用的是JDK自带的HttpUrlConection发送HTTP请求。由于JDK的HttpUrlConection没有连接池,性能和效率上相对较低。
例如当我们遇到连接超时的错误时,也能看到是HttpURLConnection
抛出的异常~这也能进一步证明默认采用的是HttpURLConnection
。
因此实际开发中,切换成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
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需要输出日志需要符合两个条件:
- FeignClient所在的包日志级别为debug
- 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次请求。
所谓念念不忘,必有回响。但……如果调用的服务器一直不能给我们回应,一直请求也不是个事儿,否则成了dos攻击了。这时候需要接受服务降级了。后续学到阿里巴巴的Sentinel,可以结合起来使用。
OpenFeign和Sentinel能够实现服务降级