什么是Feign?
Feign 是一个声明式的 REST 客户端,它用了基于接口的注解方式,很方便实现客户端配置(也就是说让客户端的远程调用变得更简单)。这里的客户端指的是服务的消费端。他的底层还是用的RestTemplate+Robbin实现。
Feign的作用是什么?
一句话,简化RestTemplate的使用,让远程调用变得更简单
怎么使用Feign呢?
使用步骤:
1、在消费端引入 open-feign 依赖
2、在启动类上使用@EnableFeignClients来开启Feign支持
3、编写Feign调用接口 ,使用相关的注解进行标注
4、注入Feign的客户端,然后通过Feign的客户端发起远程调用
具体实现:
1、在消费端引入 open-feign 依赖
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、在启动类上使用@EnableFeignClients来开启Feign支持
启动类:
@EnableDiscoveryClient // 激活DiscoveryClient 可以隐藏访问地址,用服务名称代替
@EnableEurekaClient //说明这是Eureka的客户端
@SpringBootApplication
@EnableFeignClients //开启Feign的功能
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class,args);
}
}
3、编写Feign调用接口 ,使用相关的注解进行标注
package com.itheima.consumer.feign;
import com.itheima.consumer.config.FeignLogConfig;
import com.itheima.consumer.domain.Goods;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
*
* feign声明式接口。发起远程调用的。
*
String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
Goods goods = restTemplate.getForObject(url, Goods.class);
*
* 1. 定义接口
* 2. 接口上添加注解 @FeignClient,设置value属性为 服务提供者的 应用名称
* 3. 编写调用接口,接口的声明规则 和 提供方接口保持一致。
* 4. 注入该接口对象,调用接口方法完成远程调用
*/
@FeignClient(value = "FEIGN-PROVIDER")
public interface GoodsFeignClient {
@GetMapping("/goods/findOne/{id}")
public Goods findGoodsById(@PathVariable("id") int id);
}
4、注入Feign的客户端,然后通过Feign的客户端发起远程调用
package com.itheima.consumer.controller;
import com.itheima.consumer.domain.Goods;
import com.itheima.consumer.feign.GoodsFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private GoodsFeignClient goodsFeignClient; //注入
@GetMapping("/goods/{id}")
public Goods findGoodsById(@PathVariable("id") int id){
/*
String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
// 3. 调用方法
Goods goods = restTemplate.getForObject(url, Goods.class);
return goods;*/ //用restTemplate+robbin
Goods goods = goodsFeignClient.findGoodsById(id); //用feign调用
return goods;
}
}
Feign超时配置:
Feign 底层依赖于 Ribbon 实现负载均衡和远程调用。Ribbon默认1秒超时。 如果因为提供服务端因为各种原因如网络延迟,或处理服务比较慢,比如查询数据库比较大需要耗时较多等情况造成未在一秒内给消费端返回数据就立马出问题肯定不合理,所以根据实际的业务情况得更改Feign的超时时间。
# 在客户端设置Ribbon的超时时间
ribbon:
ConnectTimeout: 1000 # 连接超时时间 默认1s
ReadTimeout: 3000 # 逻辑处理的超时时间 默认1s
Feign-日志记录配置:
首先要知道的是Feign 只能记录 debug 级别的日志信息。所以要使用feign的日志记录就必须先设置日志级别为debug。如果想清楚的知道,使用Feign来完成远程调用的时候数据传输的过程,此时就需要去设置日志。
使用步骤:
1、在配置文件中去配置日志的级别
# 设置当前的日志级别 debug,feign只支持记录debug级别的日志
logging:
level:
com.itheima: debug
2、定义一个配置类,配置日志的记录方式
package com.itheima.consumer.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignLogConfig {
/*
NONE,不记录
BASIC,记录基本的请求行,响应状态码数据
HEADERS,记录基本的请求行,响应状态码数据,记录响应头信息
FULL;记录完成的请求 响应数据
*/
@Bean
public Logger.Level level(){
return Logger.Level.FULL;
}
}
3、在@FeignClient这个注解上去通过configuration属性去使用这个配置类
package com.itheima.consumer.feign;
import com.itheima.consumer.config.FeignLogConfig;
import com.itheima.consumer.domain.Goods;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class)
public interface GoodsFeignClient {
@GetMapping("/goods/findOne/{id}")
public Goods findGoodsById(@PathVariable("id") int id);
}
通过配置文件配置:
logging:
level:
com.xt.open.jmall.product.remote.feignclients.CartFeignClient: debug
扩展:
Feign原理的简单介绍
- 启动时,程序会进行包扫描,扫描所有包下所有@FeignClient注解的类,并将这些类注入到spring的IOC容器中。当定义的Feign中的接口被调用时,通过JDK的动态代理来生成RequestTemplate。
- RequestTemplate中包含请求的所有信息,如请求参数,请求URL等。
- RequestTemplate声场Request,然后将Request交给client处理,这个client默认是JDK的HTTPUrlConnection,也可以是OKhttp、Apache的HTTPClient等。
- 最后client封装成LoadBaLanceClient,结合ribbon负载均衡地发起调用。
|