文章目录
1. 什么是Feign
Feign是Ntlix开发的声明式、模板化的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构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法-样,无需关注与远程的交互细节,更无需关注分布式环境开发。
2. Spring Cloud Alibaba 整合 OpenFeign
2.1. 第一步
添加依赖
<!--第一步、添加openfeign依赖、版本在pom.xml中的dependencyManagement已经管理-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.2. 第二步
创建接口
// 第二步、增加feign接口和方法
// name = 服务名称 / path = Controller类ReqeustMapper
@FeignClient(name = "stock-service",path = "/stock")
public interface StockFeignService {
// 声明需要调用的rest接口对应的方法
@RequestMapping("/reduct")
public String reduct();
}
/**
* 对应的服务接口
@RestController
@RequestMapping("/stock")
@Slf4j
public class StockController {
@Value("${server.port}")
private String port;
@RequestMapping("/reduct")
public String reduct(){
log.debug("扣减库存!");
return "扣减库存成功!端口:" + port;
}
}
*/
2.3. 第三步
注入接口并调用方法
// 第三步、注入feign接口,并调用方法
@Resource
private StockFeignService stockFeignService;
// 调用方法
String result = stockFeignService.reduct();
2.4. 第四步
启动类添加注解启用feign客户端
@SpringBootApplication
//Spring Cloud 原生注解 ,开启服务注册发现功能
@EnableDiscoveryClient
// 第四步、添加注解启用feign客户端
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run( OrderApplication.class, args );
}
}
3. OpenFeign自定义配置及使用
3.1. 日志配置
有时候遇到BUG,比如接口调用失败、参数没收到等问题或者查看调用性能,可以通过配置日志来把请求信息输出出来
3.1.1. 通过配置类指定日志级别
通过源码可以看到日志等级有4种,分别是:
- NONE [性能最佳,适用于生产] :不记录任何日志(默认值)。
- BASIC [适用于生产环境追踪问题] :仅记录请求方法、URL、 响应状态代码以及执行时间。
- HEADER:记录BASIC级别的基础上,记录请求和响应的header。
- FULL [比较适用于开发及测试环境定位问题] :记录请求和响应的header、body和元数据。
/**
* feign配置类
* @Author Xxx
* @Date 2021/11/22 15:20
* @Version 1.0
*/
// 全局配置 当使用@Configuration,会将配置作用所有的服务提供方
// 局部配置 如果只想针对某一个服务配置,不要加@Configuration,可以采用配置类或者配置文件
//@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel(){
/**
- NONE [性能最佳,适用于生产] :不记录任何日志(==默认值==)。
- BASIC [适用于生产环境追踪问题] :仅记录请求方法、URL、 响应状态代码以及执行时间。
- HEADER:记录BASIC级别的基础上,记录请求和响应的header。
- FULL [比较适用于开发及测试环境定位问题] :记录请求和响应的header、body和元数据。
*/
return Logger.Level.FULL;
}
}
//局部配置时通过configuration属性
@FeignClient(name = "stock-service", path = "/stock", configuration = FeignConfig.class)
3.1.2. 通过配置文件指定日志级别
# feign日志局部配置
feign:
client:
config:
product-service: # 服务名称
loggerLevel: BASIC # 日志级别
3.2. 契约配置
Spring Cloud在Feign的基础上做了扩展,使用Spring MVC的注解来完成Feign的功能。原生的Feign是不支持Spring MVC注解的,如果你想在Spring Cloud中使用原生的注解方式来定义客户端也是可以的,通过配置契约来改变这个配置,Spring Cloud中默认的是SpringMvcContract。
Spring Cloud 1 早期版本就是用的远程Feign,随着netflix的停更替换成了OpenFeign。
通常用于版本升级保留原生注解
3.2.1. 通过配置类
// 全局配置 当使用@Configuration,会将配置作用所有的服务提供方
// 局部配置 如果只想针对某一个服务配置,不要加@Configuration,可以采用配置类或者配置文件
//@Configuration
public class FeignConfig {
//修改契约配置,支持Feign原生的注解
@Bean
public Contract feignContract(){
return new Contract.Default();
}
}
//局部配置时通过configuration属性
@FeignClient(name = "stock-service", path = "/stock", configuration = FeignConfig.class)
3.2.2. 通过配置文件
# feign日志局部配置
feign:
client:
config:
product-service: # 服务名称
contract: feign.Contract.Default #设置为默认的契约,还原成原生注解
3.3. 超时时间配置
3.3.1. 通过配置类
// 全局配置 当使用@Configuration,会将配置作用所有的服务提供方
// 局部配置 如果只想针对某一个服务配置,不要加@Configuration,可以采用配置类或者配置文件
//@Configuration
public class FeignConfig {
/**
* 设置超时时间
*/
@Bean
public Request.Options options(){
return new Request.Options(5000, TimeUnit.MILLISECONDS, 10000, TimeUnit.MILLISECONDS, true);
}
}
3.3.2. 通过配置文件
# feign日志局部配置
feign:
client:
config:
product-service: # 服务名称
# 连接超时时间
connectTimeout: 5000
# 请求处理超时时间
readTimeout: 10000
3.4. 自定义拦截器
3.4.1. 通过配置类
/**
* @Author Xxx
* @Date 2021/11/22 16:48
* @Version 1.0
*/
@Slf4j
public class FeignAuthRequestInterceptor implements RequestInterceptor {
public void apply(RequestTemplate template) {
String token = UUID.randomUUID().toString();
log.debug("feign拦截器!");
template.header("Authorization", token);
}
}
// 全局配置 当使用@Configuration,会将配置作用所有的服务提供方
// 局部配置 如果只想针对某一个服务配置,不要加@Configuration,可以采用配置类或者配置文件
//@Configuration
public class FeignConfig {
/**
* 配置拦截器
*/
@Bean
public FeignAuthRequestInterceptor feignAuthRequestInterceptor(){
return new FeignAuthRequestInterceptor();
}
}
3.4.2. 通过配置文件
# feign日志局部配置
feign:
client:
config:
product-service: # 服务名称
requestInterceptors[0]: 拦截器全包名