OpenFeign
是一种声明式、模板化的 HTTP 客户端。在 Spring Cloud 中使用 OpenFeign ,可以做到使用 HTTP 请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问 HTTP 请求。
其用法就是编写一个接口,在接口上添加注解。如此就能轻而易举的调用远程服务。
有如此强大的东西,我们肯定不能放过使用的机会,就像有时你有特殊的要求必须拉别的女孩的手,而此时有个中间人能帮你实现这个愿望,你拉别的女孩子的手就像拉自己女朋友的手一样方便!
OpenFeign
在微服务中的作用就像中间方一样,当你需要调用另一个微服务的接口时,使用 OpenFeign
就像调用本服务的接口一样丝滑。
既然是远程调用,那肯定至少得有2个微服务,本系列文章已经前面已经有了几个服务,我们就调用 nacos-provider
这个服务提供者的接口。
这里新建一个 open-feign-service
子模块服务,引入 spring-cloud-starter-loadbalancer
和 spring-cloud-starter-openfeign
两个依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
父模块中添加子模块,现有模块如下:
<modules>
<module>internal-common</module>
<module>nacos-provider</module>
<module>nacos-consumer</module>
<module>nacos-config</module>
<module>sentinel-service</module>
<module>open-feign-service</module>
</modules>
如何在 open-feign-service
服务中调用 nacos-provider
服务的接口呢?前面 nacos-consumer
服务使用了 loadbalancer
和 RestTemplate
进行了调用,现在我们在 open-feign-service
服务使用 OpenFeign 来进行调用。
要将 Feign 引入到到项目中:
1. 首先需要在启动类上添加 @EnableFeignClients
注解:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OpenFeignServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OpenFeignServiceApplication.class, args);
}
}
2. 创建一个 Service 接口,添加 @FeignClient
注解:
@Service
@FeignClient(name = "nacos-provider")
public interface ProductService {
/**
* 调用远程服务 nacos-provider 的 product/{id} 接口
* @param id 参数 id
* @return 返回
*/
@GetMapping("/product/{id}")
String getProductById(@PathVariable("id") Long id);
}
关于 FeignClient
注解,需要知道:
name
: 是一个任意的客户端名称,用于创 Spring Cloud LoadBalancer 客户端;url
:url一般用于调试,可以手动指定 @FeignClient
调用的地址;configuration
:Feigin 配置类,可自定义 Feign 的 Encode,Decode,LogLevel,Contract;fallback
:定义 容错 的类,当远程调用的接口失败或者超时的时候,会调用对应接口的容错逻辑,fallback 执行的类必须实现@FeignClient
标记的接口;fallbackFactory
:工厂类,用于生成 fallback 类实例,通过此属性可以实现每个接口通用的容错逻辑,以达到减少重复的代码;path
:定义当前 FeignClient 的统一前缀。本案例只是用 name
属性指定调用的服务名称,容错属性后续可与 Sentinel 整合再说。
3. 控制层通过 FeignClient
远程调用
@RestController
public class TestController {
private ProductService productService;
@GetMapping("/product/{id}")
public String getProduct(@PathVariable("id") Long id) {
return productService.getProductById(id);
}
@Autowired
public void setProductService(ProductService productService) {
this.productService = productService;
}
}
控制层引入被 FeighClient
标记的接口 ProductService
,直接调用接口的 getProductById
方法即可实现远程调用 nacos-provider
服务的 getProduct
,这里看一下远程服务的处理逻辑:
@RestController
public class TestController {
private final static Map<Long, String> PRODUCT_MAP = new HashMap<>();
static {
PRODUCT_MAP.put(1L, "香飘飘奶茶");
PRODUCT_MAP.put(2L, "雀巢咖啡");
PRODUCT_MAP.put(3L, "百事可乐");
}
@Value("${server.port}")
private String serverPort;
@GetMapping("/product/{id}")
public String getProduct(@PathVariable Long id) {
return serverPort + ":" + PRODUCT_MAP.get(id);
}
}
直接访问本服务:http://localhost:6061/product/3 ,可以看到调用了远程服务 nacos-provider
的接口:
从结果看,还实现了访问服务的负载均衡!
OpenFeign
提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 OpenFeign
中 Http 请求的细节。 通过设置日志,可以对 Feign 接口的调用情况进行监控和输出。
OpenFeign
的日志级别主要有以下几种:
NONE
:默认的,不显示任何日志;BASIC
:仅记录请求方法、URL、响应状态码及执行时间;HEADERS
:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;FULL
:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。使用步骤:
1. 设置 Feign Logger Level:
@Bean
Logger.Level feignLoggerLevel() {
// 开启详细日志
return Logger.Level.FULL;
}
设置什么级别,根据情况而定。
2. 在配置文件中给指定的 FeignClient 接口加指定的日志级别
logging:
level:
# 给指定的 FeignClient 接口加指定的日志级别
cn.chendapeng.springcloud.openfeignservice.service.ProductService: debug
使用效果:
请求的详细情况就以日志的形式打印出来了。
spring-cloud-starter-openfeign
支持 spring-cloud-starter-loadbalancer
。我们在项目中已经添加了 spring-cloud-starter-loadbalancer
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
这样在 @FeignClient
注解中,当设定了 name = "nacos-provider"
客户端名称后,便默认使用了 Spring Cloud LoadBalancer 进行负载均衡访问 nacos-provider
,在老版本中,集成的是 Ribbon ,它默认的响应时间是 1 s,可以通过 ribbon.ReadTimeout
和 ribbon.ConnectTimeout
来设置客户端超时时间。
Spring Cloud Loadbalancer 默认没有超时时间的限制。
但是我们依然可以在默认客户端(default)和命名客户端上(注解 FeignClient 设置的 name,比如本demo中的 nacos-provider)配置超时。
OpenFeign 使用两个超时参数:
connectTimeout
防止由于服务器处理时间长而阻塞调用者。readTimeout
从连接建立时开始,在返回响应时间过长时触发。具体设置方式:
feign:
client:
config:
# 默认的超时时间设置
default:
connectTimeout: 5000
readTimeout: 5000
# 在指定的 FeignClient 设置超时时间,覆盖默认的设置
nacos-provider:
connectTimeout: 1000
readTimeout: 1000
loggerLevel: full
假如设置 nacos-provider
的超时时间为 1s ,我们通过在 nacos-provider
设置一个延迟 3 秒执行的方法,来模仿长业务线调用。
nacos-provider
的 cn.chendapeng.springcloud.nacosprovider.controller.TestController :
@GetMapping("/product/{id}")
public String getProduct(@PathVariable Long id) {
// 添加 sleep 时间,模拟超时连接
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return serverPort + ":" + PRODUCT_MAP.get(id);
}
调用效果:
❝本系列文章代码仓库:https://github.com/ChenDapengJava/SpringCloudAlibabaDemo
以上就是本文的全部内容了,本次导航结束。