OpenFeign组件
Q:使用Ribbon +RestTemplate已经可以完成服务间的调用,为何还要使用feign?
String restTemplateForObject = restTemplate.getObject("http://服务名/url?参数" + name,String.class);
存在问题:
①每次调用时都需要写以上代码,存在大量的代码冗余;
②服务地址若修改,维护成本较高;
③使用时不够灵活;
说明:
Feign是一个声明式的http客户端,它使得http客户端变得更简单,
使用feign只需要创建一个接口并注解,它具有可插拔的注解特性,可以使用SpringMVC的注解,
可使用feign注解和JAX-RS注解,
feign支持可插拔的编码器和解码器,
feign默认集成了ribbon,默认实现了负载均衡效果并且springCloud为feign添加了SpringMVC注解的支持。
OpenFeign的使用
1.引入依赖
<!--引入openfeign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.入口类开启OpenFeign支持
@SpringBootApplication
@EnableFeignClients //开启OpenFeign支持
public class UserDemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3.新建客户端接口(伪http客户端)
每一个目标服务都有一个专属客户端接口,里面写目标服务中要被调用的所有接口
如上图,由于已经创建了商品的feign并用@FeignClient注解标识,相当于在工厂中创建了client对象,在在工厂中会以代理的形式对ProductClient进行底层实现,所以调用的时候直接注入client对象即可
OpenFeign参数传递
1.单个参数传递
2.对象传递
OpenFeign超时设置
超时说明:
默认情况下,OpenFeign在进行服务调用时,要求要求服务提供方处理业务络即使见必须在1S内返回,
若超过1S未返回则OpenFeign会直接报错(Read time out executing......),不会等待服务执行,
但实际项目中往往由于处理复杂的业务逻辑,时耗会超过1S,因此需要修改OpenFeign的默认服务调用超时时间。
修改OpenFeign默认超时时间:
#以下配置不区分大小写
#配置指定服务连接超时(单位:毫秒)
feign.client.config.PRODUCTS.connectTimeout=5000
#配置指定服务等待超时(单位:毫秒)
feign.client.config.PRODUCTS.readTimeout=5000
#配置所有服务连接超时(单位:毫秒)
feign.client.config.default.connectTimeout=5000
#配置所有服务等待超时(单位:毫秒)
feign.client.config.default.readTimeout=5000
OpenFeign之日志配置
在服务调用时我们需要详细展示feign的日志,默认feign在调用时不是最详细的日志输出,
因此在调试程序时应该开启feign的详细日志展示,
feign对日志的处理非常灵活,可为每个feign客户端指定日志记录策略,
每个客户端都回创建一个logger,默认情况下logger的名字就是feign的全限定名。
需要注意的是,feign日志的打印只会DEBUG级别做出响应。
我们可为feign客户端配置各自的loggerLevel对象,告诉feign记录哪些日志,有以下几种值:
NONE 不记录任何日志
BASIC 仅仅记录请求方法、URL、响应状态代码以及执行时间
HEADERS 记录BASIC级别的基础上,记录请求和响应的header
FULL 记录请求和响应的header、body以及元数据
假设有三个微服务:用户服务、商品服务、订单服务
开启日志展示:
#开启指定服务日志展示
//只看用户服务调用商品服务的日志
feign.client.config.PRODUCTS.loggerLevel=full
#开启全局服务日志展示
//开启feign调用所有服务的日志打印
feign.client.config.default.loggerLevel=full
#指定feign调用客户端对象所在包,必须是debug级别
logging.level.feign客户端接口全限定名(到包名为止)=debug
//在以上例子中,就是ProductClient接口的全限定名