1、OpenFeign声明式客户端
Feign是Netfix开发的声明式http客户端,由于他闭源了,所以spring官方开发了OpenFeign对Feign进行了一个增强,使他支持Spring MVC的注解
1.1、OpenFeign客户端是什么
OpenFeign是一个Web声明式的Http客户端调用工具,提供接口和注解形式调用
OpenFeign是一个声明式RESTful网络请求客户端。OpenFeign会根据带有注解的函数信息构建出网络请求的模板,在发送网络请求之前,OpenFeign会将函数的参数值设置到这些请求模板中。虽然OpenFeign只能支持基于文本的网络请求,但是它可以极大简化网络请求的实现,方便编程人员快速构建自己的网络请求应用
如图所示,使用OpenFeign的Spring应用架构一般分为三个部分,分别为服务注册中心、服务提供者和服务消费者。服务提供者向服务注册中心注册自己,然后服务消费者通过OpenFeign发送请求时,OpenFeign会向服务注册中心获取关于服务提供者的信息,然后再向服务提供者发送网络请求
openFeign的位置在服务消费者方
那么这和我们之前学的ribbon有什么区别呢?
ribbon调用可以看见我们是使用链接的方式拿数据,并且还需要指定数据的接收类型,这极其不符合我们单体时候拿对象的面向对象思维,如下代码
@GetMapping("/hello")
public String hello(){
String forObject = restTemplate.getForObject("http://provider/hello/", String.class);
return "我是消费者拿生产者:"+forObject;
}
我们想实现的是以下效果:调用本地方法一样的体验
@GetMapping("/hello")
public String hello(){
String forObject = providerService.getHello();//这里替代上面写死链接的方式,看着像本地方法
return "我是消费者拿生产者:"+forObject;
}
事实上,Feign就是实现了这一功能,他封装了我们的调用,让我们通过接口的方式来调用数据,而不是写链接
同时,我们知道现在都是使用rest风格的调用,他是通过json来传输数据的,实现类似于post,get,delete,update的请求风格,原来的restTemplate就比较麻烦了
1.2、简单使用OpenFeign
1.引入依赖
<!-- 整合OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.编写feign包
我们到这里封装工具类,类似于服务提供方的controller层
/**
* name = 服务名,也就是生产者名称
* path = 指定调用rest接口所在的controller指定的@RequestMapping,其实就是路径,这里我们没有,就不写了
*/
@FeignClient(name ="provider")
public interface ProviderFeignService {
//也就是说,在这里我们rest的接收,和服务提供方接口一致
@GetMapping("hello")
String hello();
//如果我们需要使用到路径数据,也与springMVC一致
// @PostMapping("/meg/{id}")
// String get(@PathVariable Integer id);
}
3.主类添加注解@EnableFeignClients
我们可以指定扫描包,扫描到feign的包@EnableFeignClients("com.hy.feign")
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerWithOpenFeign {
public static void main(String[] args) {
SpringApplication.run(ConsumerWithOpenFeign.class, args);
}
}
4.测试调用
我们直接拿到ProviderFeignService进行面向对象方式的调用即可
@RestController
public class HelloController {
@Autowired
ProviderFeignService providerFeignService;
@GetMapping("/hello")
public String hello(){
String forObject = providerFeignService.hello();
return "我是消费者拿生产者:"+forObject;
}
}
5.如果报错类找不到
重新清理编译文件,重新编译
1.3、Feign的负载均衡
我们知道负载均衡通常使用ribbon,那么ribbon即可以通过配置类并在主类配置扫描来负载均衡,也可以修改yaml文件进行负载均衡。OpenFeign是默认继承ribbon的,所以不需要做额外的配置。
1.4、OpenFeign日志配置
Feign提供了很多扩展机制,让用户可以更加灵活的使用
1.4.1.日志配置
有时候我们遇到bug,比如接口调用失败,参数没收到等问题,或者想看看调用性能,就需要配置feign的日志了,以此让Feign把请求信息输出出来
那么我们有四个日志级别
- NONE【性能最佳,适用于生产】:不纪录任何日志(默认值)
- BASIC【适用于生产环境的追踪问题】:纪录请求方法,URL,响应状态码以及执行时间
- HEADERS:BASIC的基础上,纪录请求和响应的header
- FULL【比较适用于开发及测试环境定位问题】:路基请求和响应的header,body和原数据
1.4.1.1.配置类配置
1.定义一个配置类,指定日志级别
//如果我们添加配置类注解,那就是全局配置,所有feign客户端都会使用这么一个配置
@Configuration
public class FeignConfig {
@Bean
public Logger.Level FeignLoggerLevel() {
return Logger.Level.FULL;
}
}
2.非全局配置
如果我们不想全局配置,而是定义某个feign客户端的日志配置
第一个,我们不能在配置类中添加@Configuration
注入
并且,我们在@FeignClient
上面添加配置
// configuration = 配置类的class文件
@FeignClient(name ="provider",configuration = FeignConfig.class)
public interface ProviderFeignService {
//也就是说,在这里我们rest的接收,和服务提供方接口一致
@GetMapping("hello")
String hello();
//如果我们需要使用到路径数据,也与springMVC一致
// @PostMapping("/meg/{id}")
// String get(@PathVariable("id") Integer id);
}
3.配置开启文件日志
# 开启日志
logging:
level:
# 打印日志的全类名
com.hy.feign.ProviderfeignService: debug
4.注意
我们必须在使用@PathVariable的时候指定映射属性的名称
@FeignClient(name ="provider",configuration = FeignConfig.class)
public interface ProviderFeignService {
//@PathVariable("id")必须指定名称
@PostMapping("/meg/{id}")
String get(@PathVariable("id") Integer id);
}
1.4.1.2.配置类配置
feign:
client:
config:
provider: # 服务提供者名称
loggerLevel: BASIC
1.5、Feign契约配置
Spring Cloud在Feign的基础上做了拓展,使用Spring MVC的注解来完成Feign的功能。原生的Feign是不支持Spring MVC的功能的,如果你想在Spring Cloud中使用原生的注解方式来定义客户端也是可以的,通过配置契约来改变这个配置,Spring Cloud默认的是SpringMVCContract
为什么我用MVC注解就行还要使用这个契约配置呢?因为Spring Cloud1.0版本是使用的Feign原生注解,如果你想升级并且不想修改到MVC的代码,那么你就可以这样做
1.修改契约配置,支持Feign原生注解
@Configuration
public class FeignConfig {
/**
* 修改契约配置,支持feign原生注解
* @return
*/
@Bean
public Contract feignContract() {
return new Contract.Default();
}
}
注意:如果使用契约配置,那么将不再支持Spring MVC的注解了
2.原生注解简单使用
// 对比mvc
// @FeignClient(name ="provider",configuration = FeignConfig.class)
@FeignClient(value = "provider",path ="/provider")
public interface ProviderFeignService {
//对比mvc
//@PostMapping("/meg/{id}")
//String get(@PathVariable("id") Integer id);
@@RequestLine("GET /meg/{id}")
String get(@Param("id") Integer id);
}
3.yaml配置也可以
feign:
client:
config:
# 提供方的服务名
product-service:
#请求日志级别
loggerLevel: BASIC
contract: feign.Contract.Default #设置为默认的契约(还原成原生注解)
1.6、超时时间配置
通过Options可以配置连接超时时间和读取超时时间,Options的第一个参数是连接超时时间(ms),默认值是2s,第二个请求参数是请求处理超时时间(ms),默认值是5s
1.全局配置
@Configuration
public class FeignConfig {
@Bean
public Request.Options options() {
//五秒连接超时,十秒处理超时
return new Request.Options(5000,10000);
}
}
2.yaml配置
老样子,yaml可以精细化对于具体的服务提供者进行配置
feign:
client:
config:
provider: # 服务提供者名
# 连接超时时间,默认2s
connectTimeout: 5000
# 请求处理超时,默认5s
readTimeout: 10000
注意:Feign的底层用的是ribbon,但超时时间一Feign为准
1.7、自定义拦截器
我们服务消费方调用服务提供方的时候,可以使用我们的拦截器。比如调用的时候记录一些日志,携带token等等。
注意要和我们的前后端分离开来,在微服务项目中一般是使用网关来做前后端交互的校验
1.自定义拦截器,实现RequestInterceptor
public class FeignAuthRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
// 业务逻辑
String s = UUID.randomUUID().toString();
requestTemplate.header("Authorization",s);
}
}
2.在Feign中配置拦截器
@Configuration
public class FeignHandlerConfig {
@Bean
public FeignAuthRequestInterceptor feignAuthRequestInterceptor() {
return new FeignAuthRequestInterceptor();
}
}
标题:微服务03-OpenFeign声明式客户端
作者:1938857445
地址:https://www.lmlx66.top/articles/2022/04/25/1650861270057.html