http 客户端 Feign
持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
RestTemplate方式调用存在的问题
先来看我们以前RestTemplate发起远程调用的代码:
String url = "http://userservice"+order.getUserId();
User user = restTemplate.getForObject(url,User.class);
存在的问题:
1.代码可读性比较差
2.编程体验统一
3.参数复杂的URL难以维护
下面我们来实战feign
http客户端Feign(快速入门)
1.引入依赖(openfeign)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.在clients包下创建UserClient
记得加上注解FeignClient
@FeignClient("userservice")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
指定要请求的服务,这个等价于最上面书写的RestTemplate方式
3.在Impl里面去调用
@Autowired
private UserClient UserClient;
public Order queryOrderById(Long orderId) {
Order order = orderMapper.findById(orderId);
User user = UserClient.findById(order.getUserId());
order.setUser(user);
return order;
}
4.在启动类中加入@EnableFeignClients注解
注意:
我们点进feign的依赖包发现 ,里面已经自动集成了ribbon,因此我们无需再去配置负载均衡,feign已经帮我们做好了
自定义feign的配置
我们可以通过覆盖feign默认的配置,来自定义
一般我们需要配置的是日志的级别
有两种方式
1.property文件
例如,我们在orderservice里面写
# 全局配置
feign:
client:
config:
default:
loggerLevel: FULL
# 局部配置
feign:
client:
config:
userservice:
loggerLevel: FULL
这个时候的日志,会打印出user的接口的调用和响应,总之日志会更加全面
2.Bean配置
没那必要,不写了
Feign性能优化
Feign底层的客户端实现:
1.URL connection:默认实现,不支持连接池
这个不推荐,因为不支持连接池,你想想看,每次请求很多次握手,挥手,性能浪费的厉害
2.Apache HttpClient:支持连接池
3.OkHttp:支持连接池
因此,Feign的性能优化有两点
1.使用连接池代替默认的URLConnection
2.日志级别,最好用basic或者none,full其实挺占用内存的,嗯
Feign性能优化-连接池的配置
1.引入httpClient依赖
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
2.配置文件里面改个连接方式
feign:
client:
config:
default:
loggerLevel: Basic
httpclient:
enabled: true
max-connections: 200
max-connections-per-route: 50
max-connection是指最大连接数, max-connections-per-route是单个请求的最大连接数,这些就是连接池的配置了
Feign的最佳实践--理论
什么是最佳实践?不过是踩坑后的最好解决办法罢了
核心思想就是:抽取
思考一个场景,如果有1000个微服务,同时想要调用userservice,那么是不是每一个微服务,都需要去写一个userClient?
那么,毫无疑问,这是很烦人的,一俩个倒还行,多了就麻烦了。
为了解决这样的问题,我们需要将这个东西进行抽取,将FeignClient抽取为一个独立的模块,并且把相关的pojo类(这里是User),默认的feign配置放入其中,提供给所有消费者使用,那么这时,别的服务引入一个依赖即可
Feign的最佳实践--实现
1.新建一个新的模块 我们就叫它 feign-api-1吧(纯属自己起的名)
2.引入feign客户端依赖
<dependencies>
<!-- feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 改良feign的连接方式改成httpClient-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
</dependencies>
再加个版本吧,方便其它模块进行导入
这里是3.0版本,因为我踩了很多坑,改了很多次,才成这样!
3.将UserClient copy过来
记住,这里的方法名,参数名,还有路径一定要和User模块里面的东西一模一样!!
然后不要忘记写name,如果别人请求userservice,那么会这么请求http://userservice/user/1
4.之前用于配置feign的logs配置文件也要粘过来
public class DefaultFeignConfiguration {
@Bean
public Logger.Level logLevel(){
return Logger.Level.FULL;
}
}
然后在orderService不要忘记配置
@EnableFeignClients(clients = {UserClient.class},defaultConfiguration = DefaultFeignConfiguration.class)
这里指定了feign的UserClient,然后制定logs的配置类,
5.然后引入即可