前言
1.存在问题
远程调用可以像Autowired一样吗
服务之间的通信⽅式,通常有两种:RPC和HTTP.
在SpringCloud中,默认是使⽤HTTP来进⾏微服务的通信,最常⽤的实现形式有两种:
RestTemplate
OpenFeign
RPC(RemoteProcedureCall)远程过程调⽤,是⼀种通过⽹络从远程计算机上请求服务,⽽不需
要了解底层⽹络通信细节。RPC可以使⽤多种⽹络协议进⾏通信,如HTTP、TCP、UDP等,并且在
TCP/IP⽹络四层模型中跨越了传输层和应⽤层。简⾔之RPC就是像调⽤本地⽅法⼀样调⽤远程⽅法。
常⻅的RPC框架有:
- Dubbo:ApacheDubbo中⽂
- Thrift : Apache Thrift- Home
- gRPC:gRPC
2. OpenFeign-介绍
这个是远程调用http的另一种实现形式
OpenFeign是⼀个声明式的WebService客⼾端.它让微服务之间的调⽤变得更简单,类似controller调⽤service, 只需要创建⼀个接⼝,然后添加注解即可使⽤OpenFeign
由于Feign的停更维护,对应的,我们使⽤的依赖是spring-cloud-starter-openfeign
3. OpenFeign-快速入门
OpenFeign是远程调用的,与nacos没什么关系
所以我们就将就使用nacos代码
直接复制文件夹
改名
父项目
子项目
order调用product
所以跟product没有什么关系
我们直接在order引入依赖
feign就是openfeign
order引入注解@EnableFeignClients
这个就是开启了feign的功能
我们的远程调用要像service调用mapper一样
所以先创建一个类似mapper的
然后这个接口要绑定product里面的contorller功能
先指明这个使用的是哪个服务
然后指定找哪个接口哪个方法
这样客户端order的声明就写好了
实现的话product里面的对应的controller已经实现了
可以这样优化一下
然后就是远程调用
这样就成功了
然后开始测试
发起远程调用
OpenFeign-参数传递
单个参数
product中
然后就是
order来调用
先声明
参数用注解RequestParam来接收
而且注解RequestParam不能省略
RequestParam是接收?后面的参数
PathVariable是接收最后一个路径的
然后就是测试了
新建一个controller,然后controller调用feign,feign在调用商品服务
然后就是FeignController调用ProductApi,ProductApi调用ProductController
这样就成功了
调用order,返回product
多个参数
我们用postman来测试
然后就是feign的客户端声明了
我们可以看出feign接收对象,和单个参数的格式和springmvc是不一样的
然后就是开始测试了
对象
Json
OpenFeign-最佳实践1
我们也能看出来,Feign的客⼾端与服务提供者的controller代码⾮常相似
可以简化吗可以提出来吗
先备份一份代码
继承
把公共代码提出来,然后继承
公共代码放在哪里呢–》创建一个公共的jar包
我们在这个里面直接写方法的声明
然后引入对应的依赖
现在就还差一个ProductInfo了
我们把ProductInfo也提取出来
这样product和order都可以使用ProductInfo了
然后另外两个模块的ProductInfo就注释掉了
怎么在product中使用api呢
把api打出jar包,存在maven仓库中,然后引入
点击install,就是把当前工程打成jar包放在maven本地仓库里面
就放在这个里面
选择第一个
然后product的pom文件就多了我们刚刚打的jar包了
这样就把product-api导入product中了
order里面也是这样添加
然后就是在product中继承我们在api中的接口,然后实现
product-api中有了修改的话,就一定要重新install打包
product继承接口,然后实现接口
我们order中的feign就直接继承api中的接口就可以了
然后就是哪里有错改哪里
然后就是重新启动了
这样就成功了
OpenFeign-最佳实践
抽取
官⽅推荐Feign的使⽤⽅式为继承的⽅式,但是企业开发中,更多是把Feign接⼝抽取为⼀个独⽴的模块(做法和继承相似,但理念不同).
操作⽅法:
将Feign的Client抽取为⼀个独⽴的模块,并把涉及到的实体类等都放在这个模块中,打成⼀个Jar.服务消费⽅只需要依赖该Jar包即可.这种⽅式在企业中⽐较常⻅,Jar包通常由服务提供⽅来实现
在复制一份文件
抽取就是把这个api抽取成独立的模块
如果order有10个,那么api就要写十份,或者如果继承的话,也要继承十份
然后又是引入依赖
这样就抽取完成了
然后把order里面的productapi给注释掉
我们给profiles增加
<activation>
<activeByDefault>true</activeByDefault>
</activation>
这样每次打包的时候,都会默认勾选dev了
order也增加这个
我们在order中直接添加依赖
然后pom里面出现对应的依赖
我们把这个也给注释掉
然后就是修改包,慢慢改
我们发现有一个问题
因为spring扫描的时候默认就是扫描当前项目启动类所在的目录
所以spring-api里面的bean是扫描不到的
我们给EnableFeignClients增加指定扫描路径,clients是指定feign,basepackages是指定扫描的路径
把这个包引入进来,这样就可以打入bean了,我们用feign的注解来引入spring-api的bean
然后postman都是可以正常访问的
抽取的服务通常由服务的提供方来写
部署服务
配置的话原来就已经弄好了的
然后是打包,但是我们的maven引入了本地的包,我们在package打包的时候,是从maven中央仓库来下载这个包的
Maven打包默认是从远程仓库下载的,product-api这个包在本地,有以下解决⽅案:
上传到Maven中央仓库(参考:如何发布Jar包到Maven中央仓库,⽐较⿇烦)[不推荐]
搭建Maven私服,上传Jar包到私服[企业推荐]
从本地读取Jar包[个⼈学习阶段推荐]
我们先修改order的pom文件
scope修改为system,然后配置路径,不要反斜杠,改为斜杠
这样改一下
但是这样还不够
我们还要给springboot中的maven插件配置一下
原来:
现在:
这样设置就可以了
然后我们开始打包
先打包order
然后就是上传jar包了
然后是product的jar包
mkdir logs
nohup java -jar product-service-1.0-SNAPSHOT.jar > logs/product.log &
nohup java -jar order-service-1.0-SNAPSHOT.jar >logs/order.log &
这样就成功了