SpringCloud
一、SpringCloud–Alibaba
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。
https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
本次演示用的是G版Cloud,所以导入以下版本依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
springboot版本
<version>2.1.8.RELEASE</version>
DependencyManagement和Dependencies
Maven使用dependencyManagement元素来提供了一种管理依赖版本号的方式。
通常会在一个组织或者项目的最顶层的父POM中看到dependencyManagement元素。
使用pom.xml中的dependencyManagement元素能让所有在子项目中引用个依赖而不用显式的列出版本量。
Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用这个
dependencyManagement元素中指定的版本号。
这样做的好处就是:如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样当想升级或切换到另一个版本时,只需要在顶层父容器里更新,而不需要一个一个子项目的修改;另外如果某个子项目需要另外的一个版本,只需要声明version就可。
区别:
dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。
如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom。
如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
二、欢迎来到 Nacos 的世界!
Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos就是注册中心+配置中心的组合,Nacos = Eureka + Config + Bus
能干嘛
- 替代Eureka做服务注册中心
- 替代Config做服务配置中心
据说Nacos在阿里巴巴内部有超过10万的实例运行,已经过了类似双十一等各种大型流量的考验。
三、nacos作为服务注册中心
官网:https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md
nacos server下载
访问:https://github.com/alibaba/nacos/releases
安装
- 本地Java8+Maven环境已经OK先
- 从官网下载Nacos
- 解压安装包,cmd bin目录,启动startup.cmd
- 命令运行成功后直接访问http://localhost:8848/nacos,默认账号密码都是nacos
- 启动失败:修改startup.cmd MODE 为standalone ,然后切换默认数据库方法下面有,标题是Nacos持久化切换配置
- 结果页面
四、Spring Cloud 应用接入 Nacos Discovery
创建两个springboot项目:cloud-nacos-consumer-8001,cloud-nacos-provider-9001
1.首先,修改 pom.xml 文件,引入 Nacos Discovery Starter。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
2.在应用的 /src/main/resources/application.properties 配置文件中配置 Nacos Server 地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
3.使用 @EnableDiscoveryClient 注解开启服务注册与发现功能
测试
先启动8848Nacos注册中心
启动8001,9001
访问:http://localhost:8848/nacos
查看服务管理---->服务列表
五、nacos配置中心
简单理解配置中心的作用就是对配置统一管理,修改配置后应用可以动态感知,而无需重启。
因为在传统项目中,大多都采用静态配置的方式,也就是把配置信息都写在应用内的yml
或properties
这类文件中,如果要想修改某个配置,通常要重启应用才可以生效。
但有些场景下,比如我们想要在应用运行时,通过修改某个配置项,实时的控制某一个功能的开闭,频繁的重启应用肯定是不能接受的。
尤其是在微服务架构下,我们的应用服务拆分的粒度很细,少则几十多则上百个服务,每个服务都会有一些自己特有或通用的配置。假如此时要改变通用配置,难道要我挨个改几百个服务配置?很显然这不可能。所以为了解决此类问题配置中心应运而生。
demo
修改8001
1.首先,修改 pom.xml 文件,引入 Nacos Config Starter。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
2.在应用的 /src/main/resources/bootstrap.properties 配置文件中配置 Nacos Config 元数据
spring.application.name=cloud-nacos-consumer-8001
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
3.修改application.properties,添加以下字段,(之前的配置方式)
shy.user.name=shy
shy.user.age=18
4.添加TestController
@RestController
public class TestController {
@Value("${shy.user.name}")
private String name;
@Value("${shy.user.age}")
private Integer age;
@GetMapping("/test")
public String test(){
return name+age;
}
}
5.访问:http://localhost:8001/test
这种配置方式是否有问题?
假设这个应用已经上线了,我们需要修改源代码中的配置,改好之后需要重新将应用打包又发布上去,还需要重新刷新才能看到,这很麻烦,如果当前应用在10台机器同时部署了,就相当于配置修改之后,要给10台机器重新部署一遍。
解决方案:我们可以将配置交给配置中心,如果配置中心一改,那么就可以动态全部修改!
2021-07-09 18:03:55.812 INFO 27260 --- [ main] b.c.PropertySourceBootstrapConfiguration :
//定位数据源,NACOS-->cloud-nacos-consumer-8001.properties,配置中心中如果有这个配置文件,本地也会获取到,这个配置默认是当前的模块名+.properties
Located property source: CompositePropertySource {name='NACOS', propertySources=[NacosPropertySource {name='cloud-nacos-consumer-8001.properties'}]}
测试:访问http://localhost:8001/test 配置依然生效
但是这样又有问题来了:每次在nacos修改之后只有重启服务才能使配置生效,这样还是有点麻烦
nacos动态刷新配置
想要动态获取配置很简单
只需要配合一个注解
@RefreshScope//刷新配置,使用这个注解可以动态刷新配置,无需重启服务打包发到服务器上
修改代码后需要重启一次服务,使得配置生效。
刷新:http://localhost:8001/test
修改配置的值
刷新
问题:
Nacos
在做配置中心的时候,配置数据的交互模式是服务端推过来还是客户端主动拉的?客户端主动拉的
六、nacos命名空间与配置分组
1.命名空间*
问题 - 多环境多项目管理
问题1:
实际开发中,通常一个系统会准备
dev开发环境
test测试环境
prod生产环境。如何保证指定环境启动时服务能正确读取到Nacos上相应环境的配置文件呢?
问题2:
一个大型分布式微服务系统会有很多微服务子项目,每个微服务项目又都会有相应的开发环境、测试环境、预发环境、正式环境…那怎么对这些微服务配置进行管理呢?
环境隔离
开发,测试,生产:利用命名空间来做环境隔离
新建3个命名空间
在prop生产环境创建一个cloud-nacos-consumer-8001.properties
切换命名空间,修改bootstrap.properties
spring.application.name=cloud-nacos-consumer-8001
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=4823dd9d-8de0-466c-b88b-351d660690be
这里写的是命名空间的uuid。
重启服务,刷新:http://localhost:8001/test
微服务之间互相隔离配置
每一个微服务之间互相隔离配置,每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置
克隆配置:
选中点克隆
点击克隆即可
不同的微服务,只获取自己命名空间下的配置即可
修改consumer中的配置
修改之后发布,刷新:http://localhost:8001/test
2.配置集
所有的配置的集合
3.配置集ID*
配置集ID:类似文件名.
Data ID:类似文件名
4.配置分组*
默认所有的配置集都属于:DEFAULT_GROUP;
可以根据场景自定义组名,eg:1111,618,1212
修改bootstrap.properties
spring.application.name=cloud-nacos-consumer-8001
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=15d492ad-7b67-4c33-a2bc-f4e2a03dd95f
spring.cloud.nacos.config.group=1111
测试:重启服务,访问:http://localhost:8001/test
项目中的使用:每个微服务创建自己的命名空间,使用配置分组区分环境,dev,test,prod
5.同时加载多个配置
随着业务 的不断壮大,微服务肯有很多的配置。我们不会把所有的配置都写在本地的配置文件中,这样配置文件又多又乱,不好维护,我们一般的做法就是拆分出不同的配置文件,比如和数据源有关的配置写在某一个配置文件中,就是说根据功能拆开。
编写application.yml
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: cloud-nacos-consumer-8001
server:
port: 8001
抽取配置到nacos,
抽取完成后,把application.yml中的配置信息都注释掉
编写,bootstrap.properties
spring.application.name=cloud-nacos-consumer-8001
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=15d492ad-7b67-4c33-a2bc-f4e2a03dd95f
#spring.cloud.nacos.config.group=1111
#扩展的配置,是个list,可以写多个
#data-id:文件名
#group:分组
#refresh:是否动态刷新
spring.cloud.nacos.config.ext-config[0].data-id=port.yml
spring.cloud.nacos.config.ext-config[0].group=dev
spring.cloud.nacos.config.ext-config[0].refresh=true
spring.cloud.nacos.config.ext-config[1].data-id=spring.yml
spring.cloud.nacos.config.ext-config[1].group=dev
spring.cloud.nacos.config.ext-config[1].refresh=true
重启微服务,测试效果
访问:http://localhost:8001/test
观察日志:
Loading nacos data, dataId: 'port.yml', group: 'dev'
Loading nacos data, dataId: 'spring.yml', group: 'dev'
Loading nacos data, dataId: 'cloud-nacos-consumer-8001.properties', group: 'DEFAULT_GROUP'
Located property source: CompositePropertySource {name='NACOS', propertySources=[NacosPropertySource {name='cloud-nacos-consumer-8001.properties'}, NacosPropertySource {name='spring.yml'}, NacosPropertySource {name='port.yml'}]}
项目上线后,会把所有的配置抽取到配置中心中。
6.总结
/**
* 1、如何使用Nacos作为配置中心统一管理配置
*
* 1)、引入依赖,
* <dependency>
* <groupId>com.alibaba.cloud</groupId>
* <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
* </dependency>
* 2)、创建一个bootstrap.properties。
* spring.application.name=cloud-nacos-consumer-8001
* spring.cloud.nacos.config.server-addr=127.0.0.1:8848
* 3)、需要给配置中心默认添加一个叫 数据集(Data Id)cloud-nacos-consumer-8001.properties。默认规则,应用名.properties
* 4)、给 应用名.properties 添加任何配置
* 5)、动态获取配置。
* @RefreshScope:动态获取并刷新配置
* @Value("${配置项的名}"):获取到配置。
* 如果配置中心和当前应用的配置文件中都配置了相同的项,优先使用配置中心的配置。
*
* 2、细节
* 1)、命名空间:配置隔离;
* 默认:public(保留空间);默认新增的所有配置都在public空间。
* 1、开发,测试,生产:利用命名空间来做环境隔离。
* 注意:在bootstrap.properties;配置上,需要使用哪个命名空间下的配置,
* spring.cloud.nacos.config.namespace=9de62e44-cd2a-4a82-bf5c-95878bd5e871
* 2、每一个微服务之间互相隔离配置,每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置
*
* 2)、配置集:所有的配置的集合
*
* 3)、配置集ID:类似文件名。
* Data ID:类似文件名
*
* 4)、配置分组:
* 默认所有的配置集都属于:DEFAULT_GROUP;
* 1111,618,1212
*
* 项目中的使用:每个微服务创建自己的命名空间,使用配置分组区分环境,dev,test,prod
*
* 3、同时加载多个配置集
* 1)、微服务任何配置信息,任何配置文件都可以放在配置中心中
* 2)、只需要在bootstrap.properties说明加载配置中心中哪些配置文件即可
* 3)、@Value,@ConfigurationProperties。。。
* 以前SpringBoot任何方法从配置文件中获取值,都能使用。
* 配置中心有的优先使用配置中心中的,
*
*
*/
七、Nacos集群和持久化配置
官网:https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html
默认Nacos使用嵌入式数据库实现数据的存储。所以,如果启动多个默认配置下的Nacos节点,数据存储是存在一致性问题的。为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持MySQL的存储。
Nacos支持三种部署模式
单机模式-用于测试和单机试用。
集群模式-用于生产环境,确保高可用。
多集群模式-用于多数据中心场景。
Windows
cmd startup.cmd或者双击startup.cmd文件
单机模式支持mysql
在0.7版本之前,在单机模式时nacos使用嵌入式数据库实现数据的存储,不方便观察数据存储的基本情况。0.7版本增加了支持mysql数据源能力。
Nacos持久化切换配置
Nacos默认自带的是嵌入式数据库derby,nacos的pom.xml中可以看出。
derby到mysql切换配置步骤:新建数据库nacos
- MySQL中运行SQL文件,找到nacos-server-1.1.4\nacos\conf录下nacos-mysql.sql文件。
- nacos-server-1.1.4\nacos\conf目录下找到application.properties,添加以下配置(按需修改对应值)。
再以单机模式启动nacos,nacos所有写嵌入式数据库的数据都写到了mysql。
启动Nacos,可以看到是个全新的空记录界面,以前是记录进derby。
八、Nacos之Linux版本安装!!!
预计需要,1个Nginx+3个nacos注册中心+1个mysql
请确保是在环境中安装使用:
64 bit OS Linux/Unix/Mac,推荐使用Linux系统。
64 bit JDK 1.8+
Maven 3.2.x+
3个或3个以上Nacos节点才能构成集群。
Nacos下载Linux版,地址:https://github.com/alibaba/nacos/releases/
配置
1.把下好的包托进xftp中,注意拖进opt文件夹下~
2.解压 : tar -zxvf nacos-server-2.0.0-ALPHA.1.tar.gz
3.ll 查看,opt文件夹下出现nacos文件夹
4.cp -r nacos /mynacos/
5.切换到nacos目录:cd nacos/
6.切换到当前目录的bin目录:cd bin
Nacos集群配置
集群配置步骤(重点)
1.Linux服务器上mysql数据库配置
SQL脚本在哪里 - 目录nacos/conf/nacos-mysql.sql
自己Linux机器上的Mysql数据库上运行
执行:vim nacos-mysql.sql
双击会话,再新会话中连接数据库
新建数据库:create database nacos_config
本地MySQL连接远程服务器MySQL,连接上之后找到这个sql文件运行即可
2.application.properties配置
回到前面的窗口,查看conf文件夹下内容。
复制一份application.properties :cp application.properties application.properties.init
修改:vim application.properties
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://localhost:127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=123456
#改成你自己的数据库和账号密码
:wq退出
3.Linux服务器上nacos的集群配置cluster.conf
复制一份cluster.conf.example:cp cluster.conf.example cluster.conf
修改:vim cluster.conf
这里我是有自己的服务器的,所以这里我写的是自己的公网ip~
改完之后,保存退出
4.编辑Nacos的启动脚本startup.sh,使它能够接受不同的启动端口
/mynacos/nacos/bin目录下有startup.sh
平时单机版的启动,都是./startup.sh即可
但是,集群启动,我们希望可以类似其它软件的shell命令,传递不同的端口号启动不同的nacos实例。
命令: ./startup.sh -p 3333表示启动端口号为3333的nacos服务器实例,和上一步的cluster.conf配置的一致。
复制一份startup.sh:cp startup.sh startup.sh.bk,就是备份保个底,以后要改哪个,先备份一下,以免改坏
vim startup.sh
这里自带的p不是port,我给他改了
拉到最下面,照着改:
执行方式 - startup.sh - p 端口号
5.Nginx的配置,由它作为负载均衡器
修改nginx.conf: vim nginx.conf
这里server中除了这几行一个都不要留,因为她有默认的匹配规则,有的优先级比你配的"/"高,导致你通过nginx访问nacos 的时候访问不到。这是我磕过的绊子。
6.截止到此处,1个Nginx+3个nacos注册中心+1个mysql
启动Nacos
./startup.sh -p 3333/4444/5555
这里我的服务器内存不够了,只能启动一台,T_T
用命令:netstat -ntlp查看端口占用情况,内存不够的话真实启动了一台~
查看nacos进程启动数:
ps -ef | grep nacos | grep -v grep | wc -l
启动nginx
切换到nginx目录下
./nginx -c /usr/local/nginx/conf/nginx.conf
ps -ef|grep nginx
测试
测试通过nginx,访问nacos - http://1.117.74.89:2222/nacos/#/login
登录成功~
新建一个配置测试
新建后,可在linux服务器的mysql新插入一条记录
查询config_info表
让微服务cloudalibaba-provider-payment9002启动注册进nacos集群 - 修改配置文件
九、Nacos与其他注册中心特性对比
Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
- C在分布式系统中的所有数据备份,在同一时刻是否同样的值(等同于所有节点访问同一份最新的数据副本)
- A在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(在分布式系统中,部分节点宕机依旧不影响系统整体的运行)
- 分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做-出选择。
CAP理论就是说在分布式存储系统中,最多只能实现上面的两点。而由于网络硬件肯定会出现延迟丢包等问题,所以分区容错性是我们必须需要实现的。所以我们只能在一致性和可用性之间进行权衡,没有NoSQL系统能同时保证这三点。
Nacos支持AP和CP模式的切换
官方推荐使用A,即AP,保证其高可用
何时选择使用何种模式?
—般来说,如果不需要存储服务级别的信息且服务实例是通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。当前主流的服务如Spring cloud和Dubbo服务,都适用于AP模式,AP模式为了服务的可能性而减弱了一致性,因此AP模式下只支持注册临时实例。
如果需要在服务级别编辑或者存储配置信息,那么CP是必须,K8S服务和DNS服务则适用于CP模式。CP模式下则支持注册持久化实例,此时则是以Raft协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误。
切换命令:
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP
Nacos服务发现实例模型
十、Nacos原理
推与拉模型
客户端与配置中心的数据交互方式其实无非就两种,要么推push
,要么拉pull
。
推模型
客户端与服务端建立TCP
长连接(长连接指建立SOCKET连接后不管是否使用都保持连接),当服务端配置数据有变动,立刻通过建立的长连接将数据推送给客户端。
优势:长链接的优点是实时性,一旦数据变动,立即推送变更数据给客户端,而且对于客户端而言,这种方式更为简单,只建立连接接收数据,并不需要关心是否有数据变更这类逻辑的处理。
弊端:长连接可能会因为网络问题,导致不可用,也就是俗称的假死
。连接状态正常,但实际上已无法通信,所以要有的心跳机制KeepAlive
来保证连接的可用性,才可以保证配置数据的成功推送。
拉模型
客户端主动的向服务端发请求拉配置数据,常见的方式就是轮询,比如每3s向服务端请求一次配置数据。
轮询的优点是实现比较简单。但弊端也显而易见,轮询无法保证数据的实时性,什么时候请求?间隔多长时间请求一次?都是不得不考虑的问题,而且轮询方式对服务端还会产生不小的压力。
长轮询
开篇我们就给出了答案,nacos
采用的是客户端主动拉pull
模型,应用长轮询(Long Polling
)的方式来获取配置数据。
短轮询
不管服务端配置数据是否有变化,不停的发起请求获取配置,比如支付场景中前端JS轮询订单支付状态。
这样的坏处显而易见,由于配置数据并不会频繁变更,若是一直发请求,势必会对服务端造成很大压力。还会造成推送数据的延迟,比如:每10s请求一次配置,如果在第11s时配置更新了,那么推送将会延迟9s,等待下一次请求。
为了解决短轮询的问题,有了长轮询方案。
长轮询
长轮询可不是什么新技术,它不过是由服务端控制响应客户端请求的返回时间,来减少客户端无效请求的一种优化手段,其实对于客户端来说与短轮询的使用并没有本质上的区别。
客户端发起请求后,服务端不会立即返回请求结果,而是将请求挂起等待一段时间,如果此段时间内服务端数据变更,立即响应客户端请求,若是一直无变化则等到指定的超时时间后响应请求,客户端重新发起长链接。
OpenFeign服务调用
Ribbon本地负载均衡客户端 VS Nginx服务端负载均衡区别
Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求。即负载均衡是由服务端实现的。
Ribbon本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。
LB负载均衡(Load Balance)
集中式LB
即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx),由该设施负责把访问请求通过某种策略转发至服务的提供方;
进程内LB
将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
/**
* 1、想要远程调用别的服务
* 1)、引入open-feign
* 2)、编写一个接口,告诉SpringCloud这个接口需要调用远程服务
* 1、声明接口的每一个方法都是调用哪个远程服务的那个请求
* 3)、开启远程调用功能
*/
远程调用接口一般放在feign包下
1)、引入open-feign
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
2)、在cloud-nacos-provider-9001编写controller
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProdController {
@GetMapping("/testFeign/{name}")
public String test(@PathVariable String name){
return "用户:"+name+"调用了商品服务";
}
}
3)、编写一个接口,告诉SpringCloud这个接口需要调用远程服务,声明接口的每一个方法都是调用哪个远程服务的那个请求
package com.xinzhi.cloudnacosconsumer8001.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@FeignClient("cloud-nacos-provider-9001")
public interface TestFeign {
@GetMapping("/testFeign/{name}")
public String test(@PathVariable String name);
}
4)、开启远程调用功能,主启动类添加
@EnableFeignClients(basePackages = "com.xinzhi.cloudnacosconsumer8001.feign")
扫描feign包下的所有远程接口
5)、controller
import com.xinzhi.cloudnacosconsumer8001.feign.TestFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class TestController {
@Autowired
TestFeign feign;
@Value("${shy.user.name}")
private String name;
@Value("${shy.user.age}")
private Integer age;
@GetMapping("/test")
public String test(){
return name+age;
}
@GetMapping("/feign")
public String testFeign(){
return feign.test("xinzhi");
}
}
原理
通过 @EnableFeignCleints 触发 Spring 应用程序对 classpath 中 @FeignClient 修饰类的扫描
解析到 @FeignClient 修饰类后, Feign 框架通过扩展 Spring Bean Deifinition 的注册逻辑, 最终注册一个 FeignClientFacotoryBean 进入 Spring 容器
Spring 容器在初始化其他用到 @FeignClient 接口的类时, 获得的是 FeignClientFacotryBean 产生的一个代理对象 Proxy.
基于 java 原生的动态代理机制, 针对 Proxy 的调用, 都会被统一转发给 Feign 框架所定义的一个InvocationHandler , 由该 Handler 完成后续的 HTTP 转换, 发送, 接收, 翻译HTTP响应的工作