大家好,我是阿七。
上一篇的文章《负载均衡Ribbon》已经带大家学习过了,但是代码还是存在一些问题的,那本篇我们通过学习feign,来重构我们的代码。
feign是什么?feign是Netflix开源的声明式的http客户端。另外,摘自官网的一句话:
Feign is a declarative(声明式) web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable(可插拔) annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders. Spring Cloud adds support for Spring MVC annotations and for using the same HttpMessageConverters used by default in Spring Web. Spring Cloud integrates(集成) Ribbon and Eureka to provide a load balanced http client when using Feign.
让我们直接coding起来吧。阿七会带着大家一步一步深入了解feign。
一、整合feign
依然是我们的三步骤第一步加依赖:
org.springframework.cloud spring-cloud-starter-openfeign
第二步加注解: 启动类上加@EnableFeignClients注解
@MapperScan("com.seven")@SpringBootApplication@EnableFeignClientspublic class ContentCenterApplication { public static void main(String[] args) { SpringApplication.run(ContentCenterApplication.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }}
第三步写配置: 暂时没有配置。
第四步修改代码: 接下来我们就开始修改代码,首先我们创建一个包feignclient,编写一个接口
UserCenterFeignClient,代码如下:
//name = "user-center" 表示调用的服务名称@FeignClient(name = "user-center")public interface UserCenterFeignClient { /** * 根据ID查询用户信息,feign会自动帮我们转成 * http://user-center/users/{id} * * @param id * @return */ @GetMapping("/users/{id}") UserDTO findById(@PathVariable("id") Integer id);}
另外,我们修改内容中心调取用户中心的代码,我把之前的方法也贴出来供大家比较:before–使用ribbon调用
@Service@Slf4jpublic class ShareService { @Resource private ShareMapper shareMapper; @Resource private RestTemplate restTemplate public ShareDTO findById(Integer id) { Share share = this.shareMapper.selectByPrimaryKey(id); Integer userId = share.getUserId(); //ribbon方式:根据userId查询用户信息 UserDTO userDTO = this.restTemplate .getForObject("http://user-center/users/{userId}", UserDTO.class, userId); ShareDTO shareDTO = new ShareDTO(); BeanUtils.copyProperties(share, shareDTO); shareDTO.setWxNickname(userDTO.getWxNickname()); return shareDTO; }}
now–使用feign调用
@Service@Slf4jpublic class ShareService { @Resource private ShareMapper shareMapper; @Resource private UserCenterFeignClient userCenterFeignClient; public ShareDTO findById(Integer id) { Share share = this.shareMapper.selectByPrimaryKey(id); Integer userId = share.getUserId(); //代码演进--feign方式:直接使用feignclient来调用 UserDTO userDTO = userCenterFeignClient.findById(userId); ShareDTO shareDTO = new ShareDTO(); BeanUtils.copyProperties(share, shareDTO); shareDTO.setWxNickname(userDTO.getWxNickname()); return shareDTO; }}
这样一比较,是不是感觉我们的代码瞬间看着舒服了有木有。阿七觉得,经过一番修改,我们的代码具有以下好处:
1、可读性强了;
2、不用处理复杂的URL维护问题;
3、多人协调编程体验统一了;
那我们赶紧就来测试一下吧,启动好内容中心和用户中心服务,测试接口,哎?怎么报错了[惊呆],报错信息如下:
说什么mybatis找不到这个方法,这好奇怪啊。其实我们冷静分析一下,我们检查代码就会发现,在内容中心的启动类上,有一个mapper包扫码注解(即:@MapperScan(“com.seven”)),注解中的路径是com.seven,这样写的话,mybatis会把feignclient包中的接口也当成它的了,然后它去寻找对应的sql xml文件,当然就找不到了。所以我们应该这样修改,明确mapper接口的路径@MapperScan(“com.seven.contentcenter.dao”)。OK我们现在重启内容中心服务测试正常了。
二、feign组成
上面我们已经掌握feign的基本使用,那feign是由什么组成的呢?贴心的阿七为大家准备好了。这些可以帮助我们定位深度的问题,也方便我们去阅读源码。
三、细粒度配置feign
大家可能会发现,在我们feign调用的过程中,控制台上没有任何关于feign的日志。那作为要求严格的小伙伴,尤其在生产环境上,我们肯定想知道这个feign接口请求消耗了多长时间,是否正常啊对吧,那我们就来看看怎么把feign的日志给开启,也就是细粒度配置feign。
首先,我们要知道feign日志级别有哪些,阿七又给大家整理好了。feign默认不记录任何日志,另外生产环境设置日志级别为BASIC比较好。
配置feign日志其实很简单,我们只需在yml文件中添加下面的配置即可:
feign: client: config: #想要调用的微服务的名称 user-center: loggerLevel: fulllogging: level: #feign的日志级别必须建立在debug上,否则无效 com.seven.contentcenter.feignclient.UserCenterFeignClient: debug
那有小伙伴肯定会问了,如果内容中心调用了好多其他的微服务怎么办,难道我还要复制好多份这样的配置吗?阿七告诉你不用的,只需要简单的修改一下配置即可。但是注意一点哈,细粒度配置生效的优先级是高于全局配置的。
feign: client: config: #全局配置 default: loggerLevel: fulllogging: level: #feign的日志级别必须建立在debug上,否则无效 com.seven.contentcenter.feignclient.UserCenterFeignClient: debug
feign支持的配置项有很多,作为暖男的阿七又给大家整理好了。如果小伙伴在实际开发中遇到了,可以参考着使用。
四、feign性能优化
我们通过查看feign的底层源码看到,feign的默认使用的URLConnection去发送请求的,它是没有连接池的。但是feign底层除了使用URLConnection发送请求以外,还支持使用Apache的HTTPClient以及OKHTTP去发送请求,而Apache的HTTPClient以及OKHTTP都是支持连接池的。
性能优化1----配置连接池
配置连接池之后,性能大约能提升15%左右。
(1)、使用Apache的HTTPClient为例,来为Feign配置连接池
第一步:加依赖
io.github.openfeign feign-httpclient
第二步:写配置
feign: httpclient: # 让feign使用Apache HTTPClient做请求,而不是默认的urlConnection enabled: true # feign最大连接数 max-connections: 200 # feign单个路径的最大连接数 max-connections-per-route: 50
(2)、使用okhttp为例,来为Feign配置连接池
第一步:加依赖
io.github.openfeign feign-okhttp 10.1.0
第二步:写配置
feign: httpclient: # feign最大连接数 max-connections: 200 # feign单个路径的最大连接数 max-connections-per-route: 50 okhttp: # 让feign使用Apache okhttp做请求,而不是默认的urlConnection enabled: true
性能优化2----设置合理的日志级别
在生产环境,需要打印feign的日志,使用basic级别就ok了,强烈不建议使用full。打印日志太多,消耗feign的性能。
好了,feign的分享就到这里,最后,我画了一张微服务调用图献给大家,供小伙伴思考学习。
我们下一篇将学习服务容错–sentinel,欢迎各位小伙伴关注我,喜欢这篇文章记得点赞哦。[比心][比心][比心]