一.OpenFeign简述
OpenFeign是一个声明式的web服务客户端,它让编写web服务客户端变的非常容易,只需要创建一个接口并在接口上添加注解即可。openFeign的前身是Feign,后者目前已经停更了,openFeign是SpringCloud在Feign的基础上支持了Spring MVC的注解,并通过动态代理的方式产生实现类来做负载均衡并进行调用其他服务。
OpenFeign默认集成了Ribbon客户端,我们在使用Feign做服务调用的时候会自动加上负载均衡,所以所有针对Ribbon的配置在Feign上依然是有效地。同时我们也可以脱离Ribbon来做调用。
OpenFeign为微服务架构下服务之间的调用提供了解决方案,OpenFeign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求。
1.2为啥用OpenFeign
Feign目的就是为了使编写Java Http客户端变的更加容易。我们在使用Ribbon+RestTemplate时做服务调用时,如果被调用的服务参数比较复杂,我们在构造url时就会非常麻烦,而通过feign的话,我们只需要写一个接口,加上Spring MVC的注解,就可以实现服务调用,大大简化了我们的代码,并且增加了代码的统一性,可读性。
1.3Fegin与OpenFeign
二. OpenFeign入门案例
2.1、项目准备
2.2创建工程
在springcloudAlibaba-nacos项目上创建子服务 oorrdderr-openfeign
2.3导入依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>demo</artifactId>
<groupId>com.xinzhi.springcloud</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>oorrddeerr-openfeign</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--添加openfeign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>
2.4、编写配置
server:
port: 8040
#应用名称(nacos会将该名称当作服务名称)
spring:
application:
name: order-service
cloud:
nacos:
server-addr: 192.168.195.128:8847
discovery:
username: nacos
password: nacos
2.5、主启动类
@SpringBootApplication
//@EnableDiscoveryClient
//@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
2.6 编写接口
添加注解@FeignClient(name = "tock-service",path ="/stock")
name:指定调用rest接口所对应的服务名
path:指定调用rest接口所在的如果类上面没有RequestMapping,就不要知道path了
@FeignClient(name = "tock-service",path ="/stock")
public interface StockfeignService {
@RequestMapping("/reduct")
String reduct();
2.7 调用该接口
package com.xinzhi.controller;
import com.xinzhi.feign.ProductfeignService;
import com.xinzhi.feign.StockfeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class OrderController {
@Autowired
StockfeignService stockfeignService;
@RequestMapping("/add")
public String add(){
System.out.println("下单成功");
String reduct = stockfeignService.reduct();
return "Hello feign"+msg +s;
}
}
2.8启动测试
三. OpenFeign超时控制
3.1、超时控制介绍
默认Feign客户端只等待一秒钟,如果服务端处理需要超过1秒钟,导致Feign客户端不想等待了,直接返回报错。
为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制。
3.2、设置超时时间
打开application.yaml
,添加如下配置:
ribbon:
ReadTimeout: 5000
ConnectTimeout: 5000
四. OpenFeign日志打印
4.1、日志打印介绍
Feign提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解Feign中Http请求的细节。
简单来说,就是对Feign接口的调用情况进行监控和输出。
4.2、日志打印级别
- NONE:默认的,不显示任何日志。
- BASIC:仅记录请求方法、URL、响应状态码及执行时间。
- HEADERS:除了BASIC中定义的信息之外,还有请求和响应的头信息。
- FULL:除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据。
4.3、开启日志打印 全局配置
编写配置对象
@Configuration
@EnableFeignClients
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
springboot默认日志级别是info,feign的debug日志级别不会输出
logging:
level:
com.xinzhi.feign: debug
局部配置日志:
1. 在日志配置类中将@Configuration去掉
@EnableFeignClients
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
2.在@FeignClient(name="stick-service",path= "/stock"注解后添加,configuration = FeignConfig.class)
configuration = FeignConfig.class指的是这个接口输出日志
@FeignClient(name = "tock-service",path ="/stock",configuration = FeignConfig.class)
public interface StockfeignService {
@RequestMapping("/reduct")
String reduct();
}