hooyantsing's Blog

P26 微服务调用组件 Feign

字数统计: 1.6k阅读时长: 6 min
2022/06/21

视频源:小破站讲的最好SpringCloudAlibaba入门教程,保姆级教程通俗易懂

Java 项目中如何实现接口调用?

  1. Httpclient

    Httpclient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 http 协议的客户端编程工具包,并且它支持 HTTP 协议最新版本和建议。Httpclient 相比传统 JDK 自带的 URL Connection,提升了易用性和灵活性,使客户端发送 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。

1. 什么是 Feign

Feign 是 Netflix 开发的声明式、模板化的 HTTP 客户端。

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

1.1 优势

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

以下提到 Feign 即是 OpenFeign

2. Spring Cloud Alibaba 快速整合 OpenFeign

Step 01 引入依赖

1
2
3
4
5
<!--添加 openfeign 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

Step 02 添加 feign 接口和方法

order-openfeign 服务 feign.StockFeignService

1
2
3
4
5
6
7
// name 服务名 , path 对应服务 Controller @RequestMapping 路径
@FeignClient(name = "stock-service", path = "/stock")
public interface StockFeignService {
// 声明 Controller 是怎么样的就怎么样复制过来
@RequestMapping("/reduct")
String reduct();
}

stock-nacos 服务 controller.StockController

1
2
3
4
5
6
7
8
9
@RestController
@RequestMapping("/stock")
public class StockController {
@RequestMapping("/reduct")
public String reduct(){
System.out.println("扣减库存");
return "扣减库存";
}
}

Step 03 消费者服务调用生产者服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
@RequestMapping("/order")
public class OrderController {

@Autowired
StockFeignService stockFeignService;

@RequestMapping("/add")
public String add(){
System.out.println("下单成功");
String msg = stockFeignService.reduct();
return "Hello Feign" + msg;
}
}

Step 04 消费者服务开启 OpenFeign,使用 @EnableFeignClients 注解

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {

public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}

}

3. Spring Cloud Feign 的自定义配置及使用

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

3.1 日志配置

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

通过源码可以看到日志等级由 4 级,分别是:

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

注意,以上是 OpenFeign 的日志等级,而日志的输出又是 DEBUG 等级。

修改 SpringBoot 项目日志输出级别:

1
2
3
logging:
level:
com.tulingxueyuan.order.feign: debug
全局配置
配置类方式

Step 01 定义一个配置类,指定日志级别

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 全局配置:当使用 @Configuration 注解会将配置作用所有的服务提供方
* 局部配准:如果只想针对某一个服务进行配置,不要加 @Configuration 注解
*/
@Configuration
public class FeignConfig {

@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}

Step 02

1
2
3
4
5
6
@FeignClient(name = "product-service", path = "/product")
public interface ProductFeignService {

@RequestMapping("/{id}")
String get(@PathVariable("id") Integer id);
}
局部配置
配置类方式

Step 01 定义一个配置类,指定日志级别

1
2
3
4
5
6
7
public class FeignConfig {

@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}

Step 02

1
2
3
4
5
6
@FeignClient(name = "product-service", path = "/product", configuration = FeignConfig.class)
public interface ProductFeignService {

@RequestMapping("/{id}")
String get(@PathVariable("id") Integer id);
}
配置文件方式
1
2
3
4
5
6
# feign 日志局部配置
feign:
client:
config:
product-service: # 服务名
loggerLevel: BASIC

3.2 契约配置

作用:将 OpenFeign 的注解变更为 Feign 注解,用于老项目升级改造。

Spring Cloud 在 Feign 的基础上做了扩展,使用 Spring MVC 的注解来完成 Feign 的功能。原生的 Feign 是不支持 Spring MVC 注解的,如果你想在 Spring Cloud 中使用原生的注解方式来定义客户端也是可以的,通过配置契约来改变这个配置,Spring Cloud 中默认的是 SpringMvcContract。

Spring Cloud 1 早期版本就是用的原生 Feign,随着 Netfilx 的停更替换成了 OpenFeign。

1
2
3
4
5
feign:
client:
config:
product-service: # 服务名
contract: feign.Contract.Default # 还原成原生注解

3.4 超时时间配置

通过 Options 可以配置 “连接超时时间” 和 “请求处理超时时间”,Options 的第一个参数是连接超时时间(ms),默认值是 2s ;第二个是请求处理超时时间(ms),默认值是 5s。

1
2
3
4
5
6
feign:
client:
config:
product-service: # 服务名
connectTimeout: 5000 # 连接超时时间
readTimeout: 3000 # 请求处理超时时间

3.3 自定义拦截器实现认证逻辑

1
2
3
4
5
6
7
public class FeignAuthRequestInterceptor implements RequestInterceptor {
public void apply(RequestTemplate template) {
// 业务逻辑
String access_token = UUID.randomUUID().toString();
template.header("Authorization",access_token);
}
}
1
2
3
4
5
6
7
8
// 全局配置
@Configuration
public class FeignConfig {
@Bean
public FeignAuthRequestInterceptor feignAuthRequestInterceptor() {
return new FeignAuthRequestInterceptor();
}
}
CATALOG
  1. 1. Java 项目中如何实现接口调用?
  2. 2. 1. 什么是 Feign
    1. 2.1. 1.1 优势
  3. 3. 2. Spring Cloud Alibaba 快速整合 OpenFeign
  4. 4. 3. Spring Cloud Feign 的自定义配置及使用
    1. 4.1. 3.1 日志配置
      1. 4.1.1. 全局配置
        1. 4.1.1.1. 配置类方式
      2. 4.1.2. 局部配置
        1. 4.1.2.1. 配置类方式
        2. 4.1.2.2. 配置文件方式
    2. 4.2. 3.2 契约配置
    3. 4.3. 3.4 超时时间配置
    4. 4.4. 3.3 自定义拦截器实现认证逻辑