OpenFeign篇
声明式Rest客户端
-
指定远程地址:@FeignClient
-
指定请求方式:@GetMapping,@PostMappring,@DeleteMapping,@PutMapping
-
指定携带数据:@RequestHeader,@RequestParam,@RequestBody,...
Springboot 整合Openfeign
1、引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、在应用入口开启feign客户端
@SpringBootApplication
// 启用nacos发现客户端
@EnableDiscoveryClient
// 启用feign客户端
@EnableFeignClient
public class Order{
public static void main(){
xxx
}
}
3、声明接口
创建一个包专门存放feign客户端
// 声明客户端,并绑定指定的微服务
@FeignClient("service-product")
public interface ProductFeignClient {
/**
* 在controller中标注就表示接收这样的请求
* 但在feignClient中标注则表示发送这样的请求
*/
// 与product中的controller保持一致就行
@GetMapping("/product/{id}")
Product getProductById(@PathVariable("id") String id);
}
4、使用Openfeing
@Autowired
private ProductFeignClient productFeignClient;
@GetMapping("/create/{userId}/{productId}/{number}")
public Order createOrder(@PathVariable("userId") String userId,
@PathVariable("productId") String productId,
@PathVariable("number") int number){
// 使用Openfeign远程调用
Product productFromRemote = productFeignClient.getProductById(productId);
Order order = new Order();
order.setId("001");
order.setAddress("Taurus-Home");
order.setUserId(userId);
// 需要远程调用获取商品信息
List productList=new ArrayList<>();
productList.add(productFromRemote);
order.setProductList(productList);
// 需要远程调用获取价格
order.setTotalAmount(number* productFromRemote.getPrice());
return order;
}
5、日志监控
在application中配置
# 开启openfeign的日志
logging:
level:
org.missying.feign: debug
配置全记录
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
6、超时控制
如果服务器宕机 ;连接不上
或者API响应速度慢 ;读取不到数据
两种超时:
-
连接超时-> 建立连接,默认超时时间是10s
-
读取超时-> 发送数据并返回数据,默认超时时间是60s
spring:
cloud:
openfeign:
client:
config:
# 如果没有设置会用默认的,
# 这里修改了默认的连接超时和读取超时
default:
connect-timeout: 5000
read-timeout: 10000
service-product:
# 日志级别设置的另一种方式
logger-level: full
# 连接超时3s
connect-timeout: 3000
# 读取超时5s
read-timeout: 5000
7、重试机制
默认情况下是不会重试的,需要自己设置
另外重试的时间也是有特殊的间隔
方式一:可以在配置文件中配置retryer
spring:
cloud:
openfeign:
client:
config:
# 默认配置
default:
connect-timeout: 5000
read-timeout: 5000
retryer: feign.Retryer.Default
# 针对某个微服务的
cloud-singer:
connect-timeout: 10000
read-timeout: 5000
retryer: feign.Retryer.Default
方式二:创建Bean文件
@Bean
Retryer retryer(){
return new Retryer.Default();
}
8、拦截器
请求拦截器:在请求前,对请求做一定的修改,比如添加token等
@Component
public class XTokenRequestInterceptor implements RequestInterceptor {
/**
* 请求拦截器
* @param requestTemplate 请求模板,里面有请求的相关信息,比如请求头,请求体等
* */
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header("X-Token","Taurus-William");
}
}
响应拦截器:处理结果之后再返回处理后的结果
@Component
@Slf4j
public class singerFeignResInterceptor implements ResponseInterceptor {
@Override
public Object intercept(InvocationContext invocationContext, Chain chain) throws Exception {
log.info("响应拦截器");
Response response = invocationContext.response();
response.headers().forEach((key,value)->{
System.out.println(key+"-->"+value);
});
// 一定要记得,否则会出现空指针异常
return chain.next(invocationContext);
}
}
9、兜底回调
这需要结合sentinel才能实现
a) 导入sentinel的依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
b) 创建新的包和类来实现请求接口
@Component
public class ProductFeignClientFallback implements org.missying.feign.ProductFeignClient {
@Override
public Product getProductById(String id) {
Product product = new Product();
product.setId("1");
product.setName("兜底名称");
product.setPrice(0);
product.setNumber(0);
return product;
}
}
c) 在接口函数中设置
@FeignClient(value = "service-product",fallback = ProductFeignClientFallback.class)
public interface ProductFeignClient {
/**
* 在controller中标注就表示接收这样的请求
* 但在feignClient中标注则表示发送这样的请求
*/
@GetMapping("/product/{id}")
Product getProductById(@PathVariable("id") String id);
}
之后如果访问超时或者错误,且尝试结束之后仍得不到结果,就会返回兜底结果