2.2 Feign远程调用
一、基于Feign远程调用
RestTemplate请求中存在的问题
代码可读性差,编程体验不统一
参数复杂,URL难以维护
Feign的介绍
Feign是一个声明式的http客户端,官方地址是https://github.com/OpenFeign/feign,所用是帮助我们优雅的实现http请求的发送,解决RestTemplate存在的问题
使用Feign的步骤:
引入Feign依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>在调用方(消费方)的启动类中添加注解,开启Feign的功能
@SpringBootApplication @MapperScan("cn.learn.order.mapper") @EnableFeignClients // 开启Feign远程调用 public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } }使用编写Feign客户端
@FeignClient("user-service") // 声明远程调用的服务 public interface UserServiceClient { // 这是一个接口 @GetMapping("/user/{id}") // 声明请求方式以及请求全路径 User findById(@PathVariable("id") Long id); // 请求方法以及参数 }备注:这是所有对user-service发起的远程调用
Feign自动实现负载均衡
使用:
@Service public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService { @Autowired private RestTemplate restTemplate; @Autowired private UserServiceClient userServiceClient; @Override public OrderVO getByOrderId(Long id) { Order order = this.getById(id); OrderVO orderVO = BeanHelper.copyProperties(order, OrderVO.class); // 使用Feign远程调用 User user = userServiceClient.findById(order.getUserId()); orderVO.setUser(user); return orderVO; } }注意:
SpringCloud的Feign在Hoxton.M2 RELEASED版本后不再使用Ribbon进行负载均衡,而是使用spring-cloud-loadbalancer
因此,如果使用Hoxton.M2 RELEASED版本周的Feign,就需要直接调用方中假如坐标
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency>由于Nacos的discovery中使用了Ribbon,并且这个Ribbon会使loadbalancer失效,因此,使用了Nacos,需要将Ribbon提出
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <exclusions> <exclusion> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </exclusion> </exclusions> </dependency>
二、自定义配置
Feign运行自定义配置来覆盖默认配置,可修改配置如下:
类型作用说明feign.Logger.Level
修改日志级别
包含四种不同的级别:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder
相应结果的解析器
http远程调用的结果做解析,例如解析jaon字符串为Java对象
frign.cloudec.Encoder
请求参数编码
将请求参数编码,便于通过http请求发送
feign.Contract
支持的注解格式
默认是SpringMVC的注解
feign.Retryer
失败重试机制
请求失败的重试机制,默认是没有,比不过会使用Ribbon的重试
备注:一般配置的就是日志级别
日志级别解释:NONE:默认、BASIC:基本请求、HEADERS基本请求+请求头、FULL:所有日志信息
修改日志级别的方式:
基于配置文件修改:
# 全局生效 feign: client: config: default: # default就是全局配置,如果是服务名就是针对某个服务配置,局部 loggerLevel: FULL # 局部生效 feign: client: config: user-service: # 针对user-service服务的配置 loggerLevel: FULL基于Java代码的配置
// 声明一个Bean public class FeignClientConfiguration { @Bean public Logger.Level feignLogLevel() { return Logger.Level.BASIC; } } // 全局配置 @EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class) // 局部配置 @FeignClient(vlaue = "user-service", configuration = FeignClientConfiguration.class)
三、Feign的性能优化
底层客户端实现
URLConnection:默认实现,不支持连接池
Appache HttpClient:支持连接池
OkHttp:支持连接池
优化Feign的性能主要包括
使用连接池代替默认的URLConnect
日志级别,最好使用basic活none
修改连接池为HttpClient
添加依赖:
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency>配置连接池
feign: client: config: default: # 全局配置 loggerLevel: BASIC # 日志级别,基本响应信息 httpclient: enabled: true # 开启feign对HttpClient的支持 max-connections: 200 # 最大连接数 max-connections-per-route: 50 # 每个路径最大连接数量备注:连接数与每个路径的最大连接数需要压力测试后才可以给出最优量
如果使用OkHttp则需要将httpclient修改为okhttp,并添加OkHttp的坐标依赖
四、Feign最佳实践
方式一:继承
给消费者的FeignClient和提供者的Controller定义统一的父接口作为标准
定义统一接口声明,Controller以及FeignClient同时实现这个接口
官方不推荐,因为耦合性太高;父接口参数列表中的映射不被继承
方式二:抽取
将FeignClient抽取为独立模块,并且吧接口有关的pojo、默认的Feign配置都放在这个模块中,提供给所有的消费者
缺点:每个服务都要引入所有的服务
会出现的问题:指定的连接类找不到
指定FeignClient所在包
@EnableFeignClients(basePackages = "包地址")指定FeignClient字节码(推荐)
@EnableFeignClients(clients = {文件名.class})
最后更新于
这有帮助吗?