微服务调用组件Feign服务的调用方式,以及全局、局部日志的配置方式

717 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

JAVA 项目中如何实现接口调用?
1)Httpclient

HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 Http 协议的客户端编程工具包,并且它支持 HTTP 协议最新版本和建议。HttpClient 相比传统 JDK 自带的 URLConnection,提升了易用性和灵活性,使客户端发送 HTTP 请求变得容易,提高了开发的效率。

2)Okhttp

一个处理网络请求的开源项目,是安卓端最火的轻量级框架,由 Square 公司贡献,用于替代 HttpUrlConnection 和 Apache HttpClient。OkHttp 拥有简洁的 API、高效的性能,并支持多种协议(HTTP/2 和 SPDY)。

3)HttpURLConnection

HttpURLConnection 是 Java 的标准类,它继承自 URLConnection,可用于向指定网站发送 GET 请求、POST 请求。HttpURLConnection 使用比较复杂,不像 HttpClient 那样容易使用。

4)RestTemplate WebClient

RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率。

上面介绍的是最常见的几种调用接口的方法,我们下面要介绍的方法比上面的更简单、方便,它就是 Feign。

一、什么是Feign

Feign是Netflix开发的声明式、模板化的HTTP客户端,其灵感来自Retrofit、JAXRS-2.0以及WebSocket。Feign可帮助我们更加便捷、优雅地调用HTTP API。

Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。

Spring Cloud openfeign对Feign进行了增强,使其支持Spring MVC注解,另外还整合了Ribbon和Nacos,从而使得Feign的使用更加方便

1-1、优势

Feign可以做到使用 HTTP 请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。它像 Dubbo 一样,consumer 直接调用接口方法调用 provider,而不需要通过常规的 Http Client 构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。

二、Spring Cloud Alibaba快速整合OpenFeign

2-1、引入依赖

<!-- openfeign 远程调用 --> 
<dependency> 
    <groupId>org.springframework.cloud</groupId> 
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2-2、编写调用接口+@FeignClient注解

在服务消费端,添加一个服务接口,添加@FeignClient注解,其中value的值为被调用服务的服务名称,path则为调用的最终服务路径,也就是之前Controller上@RequestMapping注解的路径。

下面的sub方法,可以理解为就是一个原来实现方法的接口,最终实现如下: image.png

2-3、调用端在启动类上添加@EnableFeignClients注解

在启动类上加上@EnableFeignClients注解,否则在实现类中注入StockFeignService就会报错。 image.png

2-4、发起调用,像调用本地方式一样调用远程服务

将上面写的添加了@FeignClient注解的StockFeignService的类注入到类中,这样就可以直接调用其下面的方法了,实际上最终实现的原理,就是使用了代理。后面再深剖Feign的时候再进行介绍 image.png

2-5、测试

可以看到、这样不用RestTemplate也可以实现服务的调用了。 image.png

三、Spring Cloud Feign的自定义配置及使用

Feign 提供了很多的扩展机制,让用户可以 更加灵活的使用。

3-1、日志配置

有时候我们遇到 Bug,比如接口调用失败、参数没收到等问题,或者想看看调用性能,就需要配置 Feign 的日志了,以此让 Feign 把请求信息输出来。

3-1-1、全局日志配置

3-1-1-1、定义一个配置类,指定日志级别

配置一个Feign的日志配置类,需要注意的是类上面的@Configuration,添加之后就针对所有feign添加日志,如果不加那就只能设置局部的feign服务,同时Logger引用的包是Feign.Logger。 image.png 通过源码可以看到日志等级有 4 种,分别是:

  • NONE【性能最佳,适用于生产】:不记录任何日志(默认值)。
  • BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间。
  • HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
  • FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据。

3-1-1-2、在stock-server中添加一个get方法

模拟一个通过ID查询商品库存的服务,通过ULR进行传参 image.png

3-1-1-3、在order-service服务消费端,通过feign进行声明

通过声明接口,启动服务发现启动失败,如下: image.png 通过分析可以看到是@PathVariable的问题,在springboot中使用@PathVariable不用写value,但是在使用Feign的时候就需要加上value了,整体写法:@PathVariable(value="id"),完整代码如下:

@RequestMapping("get/{id}")
public String get(@PathVariable(value = "id") String id);

3-1-1-4、控制器调用商品库存服务

image.png

3-1-1-5、测试调用库存服务

可以看到已经成功在order-service调用stock-service的服务 image.png

这个时候看日志是没有任何输出的,原因是虽然给Feign的日志设置了FULL,但是spring的默认日志级别是info,这样debug级别的日志就无法输出了,因此需要修改一些spring的日志级别,但是又不想修改所有程序,因此旧单独针对api中的添加入职级别

image.png

3-1-1-5-1、修改feign接口的日志级别

在配置文件中添加日志级别配置 image.png

3-1-1-5-2、再次访问接口,查看日志

这样就可以给所有的feign设置日志级别了 image.png

3-1-2、局部配置,让调用的微服务生效,

3-1-2-1、通过配置类设置,在@FeignClient 注解中指定使用的配置类

这时候FeignConfig上面的@Configuration需要去掉 image.png

然后再feign服务商添加FeignConfig image.png

3-1-2-1-1、测试

再次访问接口,可以看到仍然可以获得日志,如果此时api包中有其他feign服务,并且没有配置FeignConfig那么就无法输出日志了。 image.png

3-1-3、通过配置文件,是局部Feign日志生效

feign:
  client:
    config:
      stock-service:  #对应微服务
        loggerLevel: FULL

image.png