HTTP客户端Feign
一、Feign替代RestTemplate
- RestTemplate方式调用存在的问题
我们之前使用RestTemplate发起远程调用的代码:
//2.1url路径
String url = "http://userservice/user/"+order.getUserId();
//2.2发送http请求,实现远程调用
User user = restTemplate.getForObject(url, User.class);
存在下面的问题:
1、代码可读性差
2、参数复杂情况下的URL难以维护
- Feign的介绍
Feign是一个声明式的http客户端,官方地址:https://github.com/OpenFeign/feign
其作用是帮助我们实现http请求的发送,解决上面提到的问题
- 定义和使用Feign客户端
使用步骤:
1、引入依赖:
<!--feign客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、在order-service的启动类添加注解开启Feign的功能:
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
3、编写Feign客户端:
@FeignClient("userservice")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private UserClient userClient;
public Order queryOrderById(Long orderId) {
//1、查询订单
Order order = orderMapper.findById(orderId);
//2、用Feign远程调用
User user = userClient.findById(order.getUserId());
//3、封装user到Order
order.setUser(user);
//4、返回
return order;
}
}
二、自定义配置
Feign运行自定义配置来覆盖默认配置,可以修改的配置如下:
一般我们需要配置的就是日志级别。
配置Feign日志有两种方式:
方式一:配置文件方式
①全局生效(在order-service中尝试配置)
②局部生效
方式二:Java代码方式
需要先声明一个Bean:
①而后如果是全局配置,则把它放到@EnableFeignClients这个注解中:
②如果是局部配置,则把它放到@FeignClient这个注解中:
三、Feign性能优化
Feign底层的客户端实现:
- URLConnection:默认实现,不支持连接池
- Apache HttpClient:支持连接池
- OKHttp:支持连接池
因此优化Feign的性能主要包括:
①使用连接池代替默认的URLConnection
②日志级别,最好用basic或none
- Feign添加HttpClient的支持
在order-service中引入依赖
<!--引入HttpClient依赖-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
给order-service配置连接池
feign:
httpclient:
enabled: true #支持HttpClient的开关
max-connections: 200 #最大连接数
max-connections-per-route: 50 #单个路径的最大连接数
四、最佳实践
- Feign的最佳实践
方式一(继承):给消费者的FeignClient和提供者的Controller定义统一的父接口作为标准
一般不推荐这种方式,因为可能会造成紧耦合,即耦合度太高
方式二(抽取):将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用
即将FeignClient、POJO、Feign的默认配置都定义到一个项目中,供所有消费者使用
- 抽取FeignClient
实现最佳实践方式二的步骤如下:
1、首先创建一个moudle,命名为feign-api,然后引入feign的starter依赖
2、将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中
3、在order-service中引入feign-api
<!--引入feign的统一api-->
<dependency>
<groupId>cn.itcast.demo</groupId>
<artifactId>feign-api</artifactId>
<version>1.0</version>
</dependency>
4、修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包
当定义的FeignClient不再SpringBootApplication的扫描包范围内时,这些FeignClient无法使用,有两种方式解决:
方式一:指定FeignClient所在的包
方式二:指定FeignClient字节码
5、重启测试