在之前的博客中,我们介绍了RestTemplate的使用,博客文章如下连接。但是在使用RestTemplate的时候,需要把生产者的路径拼出来,非常繁琐,另外参数的传递的也比较繁琐,解决方案就是使用openFeign。
SpringCloud入门(RestTemplate + Ribbon)——微服务调用的方式 & RestTemplate的使用 & 使用nacos的服务名初步(Ribbon负载均衡)
本篇博客介绍OpenFeign,声明式的HTTP客户端,用于简化服务间的调用这一SpringCloud组件,并尝试对源码进行了初步分析。
1.spring提供的restTemplate,发送HTTP请求的客户端工具类;
2.OpenFeign,声明式的HTTP客户端,用于简化服务间的调用;
3.和ribbon的关系,其他的配置,超时时间,日志级别;
4.源码分析,@EnableFeignClient和@FeignClient的作用;
5.尝试分析OpenFeign请求发送的流程;
声明式的HTTP客户端,用于简化服务间的调用
OpenFeign的主要特点和功能包括:
总之,OpenFeign简化了微服务架构中的服务间调用,提供了一种简洁、声明式的方式来定义和调用服务API。它与Spring Cloud的其他组件集成良好,是构建和管理微服务架构的重要工具之一。
上面的代码存在以下问题:
因此采用OpenFeign技术来解决上述问题
Feign是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求。
Spring Cloud Feign是基于Netflix feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix 实现负载均衡和断路器,除了提供这两者的强大功能外,还提供了一种声明式的Web服务客户端定义的方式。
Spring Cloud Feign帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring CloudRibbon时自行封装服务调用客户端的开发量。
通俗的讲:feign使远程调用的代码写法更加符合我们的编程习惯,也内置了负载均衡策略。
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
<version>2.2.6.RELEASEversion>
dependency>
import org.springframework.cloud.openfeign.EnableFeignClients;
package com.tianju.consumer.api;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
// contextId唯一,可以随便写;
//@FeignClient(value = "springCloud-provider",contextId = "providerFeignTest") // openfeign用来远程连接
@FeignClient(value = "springCloud-provider",fallback = ProvideFallback.class) // openfeign用来远程连接
public interface IProvideFeign {
@GetMapping("/api/provider/hello")
String helloFeign();
/**
* 这个去调用生产者provider
* @param msg 路径变量信息
* @return 返回结果
*/
@GetMapping("/api/provider/hiPath/{msg}")
String pet(@PathVariable("msg") String msg);
}
@Autowired
private IProvideFeign feign;
@GetMapping("/hiCall")
public String callFeign(){
String s = feign.helloFeign();
System.out.println(s);
System.out.println("消费者获取生产者提供的数据"+s);
return s;
}
注意事项:
从上面的feign使用可以知道,ProductFeignClient是一个接口,我们在OrderController中注入的
ProductFeignClient不可能是一个接口,肯定是一个实例化的对象。
Ribbon是一个基于 HTTP 和 TCP 客户端 的负载均衡的工具。它可以 在客户端 配置RibbonServerList(服务端列表),使用 HttpClient 或 RestTemplate 模拟http请求,步骤相当繁琐。
Feign 是在 Ribbon的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。采用接口的方式, 只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方法即可, 不需要自己构建http请求。然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写客户端变得非常容易。
消费端进行配置
feign:
# 打开阿里的 sentinel
sentinel:
enabled: true
# 调用生产者的配置
client:
config:
springCloud-provider:
connect-timeout: 3000 # 连接超时时间,单位毫秒,默认2秒
read-timeout: 3000 # 处理请求的时间,默认是5s
生产者进行线程的休眠
@GetMapping("/hello")
public String hello(){
String s = "服务"+serverId+",端口:"+port+",电影名:"+movieName;
System.out.println(s);
try {
Thread.sleep(4000); // 生产者休眠4s之后响应
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return s;
}
消费者调用feign报错500
Spring Cloud Feign 支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。通过下面的参数,即可开启请求与响应的压缩功能:
feign:
# 打开阿里的 sentinel
sentinel:
enabled: true
# 调用生产者的配置
client:
config:
springCloud-provider:
connect-timeout: 3000 # 连接超时时间,单位毫秒,默认2秒
read-timeout: 3000 # 处理请求的时间,默认是5s
compression:
request:
enabled: true # 开启请求压缩,默认为false
# 设置支持压缩的数据类型
mime-types: text/html,application/xml,application/json
# 设置触发压缩的数据下限
min-request-size: 1 # 2048 2M?
response:
# 开启响应压缩,默认值为false
enabled: true
在开发或者运行阶段往往希望看到Feign请求过程的日志记录,默认情况下Feign的日志是没有开启的。
要想用属性配置方式来达到日志效果,只需在 application.yml 中添加如下内容即可:
日志级别
feign:
# 打开阿里的 sentinel
sentinel:
enabled: true
# 调用生产者的配置
client:
config:
springCloud-provider:
connect-timeout: 3000 # 连接超时时间,单位毫秒,默认2秒
read-timeout: 3000 # 处理请求的时间,默认是5s
loggerLevel: BASIC # 设置feign调用的日志级别 NONE BASIC HEADERS FULL
配置文件的方式配置,只能针对某一个服务起作用,可以使用配置类的方式进行配置
级别 | 解释 |
---|---|
NONE | 默认的,不显示任何日志 |
BASIC | 仅记录请求方法、URL、响应状态码及执行时间 |
HEADERS | 除了 BASIC 中定义的信息之外,还有请求和响应的头信息 |
FULL | 除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据 |
在consumer-feign中添加feign日志配置类,指定日志输出级别以显示指定的内容
注意Level的包为:feign.Logger
package com.tianju.consumer.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 定义feign的日志打印级别,作为全局的日志输出控制
* @return
*/
@Configuration
public class FeignLogConfig {
@Bean
public Logger.Level level(){
return Logger.Level.FULL;
}
}
因为feign日志的输出级别都是debug级别,因此如果想要看到日志信息,还需要设置service包的日志级别
logging:
level:
com.tianju.consumer: debug
此时再调用就会显示feign的日志
通过上面的使用过程,@EnableFeignClients和@FeignClient两个注解就实现了Feign的功能,那我们从
@EnableFeignClients注解开始分析Feign的源码
通过 @EnableFeignClients 引入了FeignClientsRegistrar客户端注册类
然后通过registerFeignClient 注册了feign客户端对象
创建代理对象注册到spring容器中
工厂模式,生成feign的bean工厂
创建代理对象
FeignClientFactoryBean.getObject()具体返回的是一个代理类,具体为FeignInvocationHandler,调
用该类中的invoke方法
先要找到url
先在feign的核心包中,找到生产者的url
紧着这获取了后面拼的路径
拿到路径
两者拼一下,然后把生产者url作为消费者的url的一个子路径请求
invoke方法执行创建RequestTemplate
类似于RestTemplat
执行生产者的调用feign的map,似乎是一个一个调用,获取响应
1.spring提供的restTemplate,发送HTTP请求的客户端工具类;
2.OpenFeign,声明式的HTTP客户端,用于简化服务间的调用;
3.和ribbon的关系,其他的配置,超时时间,日志级别;
4.源码分析,@EnableFeignClient和@FeignClient的作用;
5.尝试分析OpenFeign请求发送的流程;