OpenFeign
OpenFeign
底层实现上:
- 获取到你正在运行的实例(instance(也即是注册在nacos等注册中心的applicationName))
- 编辑请求(包括函数的url,参数,方法,返回值等)(通常是调用一些方法来构成这个请求)
- 负载均衡:最烂的做法就是获取总共的该服务有多少instance然后在其中取个随机值即可
- 发送,然后处理返回值
调用OpenFeign
- 导包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>3.1.5</version>
</dependency>
- 使用上:
- configuration类或者其他配置类上添加注解@EnableFeignClients
- 在每个FeignClient中都采用类似MVC的方式:不同的是没有方法体和要加上注解@FeignClient(
"对应服务的applicationName")
如下:
@FeignClient("gulimall-product")
public interface ProductFeignService {
@RequestMapping("/product/skuinfo/info/{skuId}")
public R info(@PathVariable("skuId") Long skuId);
@RequestMapping("/product/skusaleattrvalue/getSkuSaleAttrList/{skuId}")
public R getSkuSaleAttrList(@PathVariable("skuId") Long skuId);
@GetMapping("/product/skuinfo/{skuId}/price")
public BigDecimal getPrice(@PathVariable("skuId") Long skuId);
}
需要注意的点
- 在描写路径时,要精准描写
连接池(性能提升)
其实openFeign的代码并不直接支持发送http请求,而是利用其他的依赖来发送,而默认的依赖是不支持连接池的
总共支持的依赖有如下几种:
以OKHttp为例:
步骤
- 导依赖
<!--OkHttp,为feign带来了连接池 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>12.5</version>
</dependency>
- 更改配置文件
#okHttp
feign.okhttp.enabled=true
分布式项目的最佳实践
由于feignservice一直需要被调用,
所以有两种主流做法:
- 把每一个可能被远程调用的服务继续细分(3份)
- DTO
- api(放feignService的)
- biz(业务代码)
- 弄一个统一的模块类似(common)的guli-api
- 然后其他服务依赖这个服务
虽然第二种做法,看起来不那么分布式,但是它结构简答了许多,更常用
远程调用开启日志
前提
你本来服务就开启了日志,且等级为debug及以上
开启方法
配置一个配置类
@Configuration
//@ConditionalOnClass(DispatcherServlet.class),直接弄一个enable的注解得了
public class GuliFeignConfig {
@Bean
public Logger.Level level(){
return Logger.Level.BASIC;
}
}
共有以下四种类型
闲谈
在制作配置类时,像FeignConfig我们在绝大多数服务中都会用到,所以注入时有经验的
目前情况
- config没在我们默认的扫描范围
- 且部分服务如gateway由于使用webflux不能同时使用mvc(这点在目前体现不出,但在之后:要注入:RequestInterceptor时会冲突)
解决方法(针对第一个情况)
- 在启动类设置scanBasePackages()
- 弄一个spring.factories文件,在里面写好要配置的configuration类
- 弄一个annotation(@EnableFeignConfig),在其之上加上@import("配置类"),之后只要用到该注解则会自动导入
解决方法(针对第2个情况)
- 设置@ConditionalOnClass(DispatcherServlet.class)
- 在部分服务导入依赖时用exclusions