前面已经学习了Eureka注册中心,为什么还要学习Nacos注册中心。
原因: Nacos是阿里巴巴的产品,现在是SpringCloud中的一个组件。相比于Eureka功能更加丰富,在国内受欢迎程度较高
nacos下载链接
链接:https://pan.baidu.com/s/1hxt4Kn8ChcoGkarmuV95gA
提取码:mfkw
第一步: 在D盘新建Nacos目录,把下载下来的nacos压缩包复制到D盘下的Nacos目录,并解压
第二步: 查看nacos的启动端口

第三步: 启动nacos。进入nacos包的bin目录,命令行打开。m表示启动模式,standalone表示单机启动。除了单机启动模式,还有集群启动的模式
startup.cmd -m standalone

第四步: 浏览器访问,访问上面的路径


第一步: 在cloud-demo父工程中添加spring-cloud-alibaba的管理依赖,作用是管理nacos版本
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-alibaba-dependenciesartifactId>
- <version>2.2.5.RELEASEversion>
- <type>pomtype>
- <scope>importscope>
- dependency>
第二步: 在order-service和user-service微服务的pom.xml里面,注释掉原有的eureka依赖
第三步: 在order-service和user-service微服务的pom.xml里面,添加nacos的客户端依赖
- <dependency>
- <groupId>com.alibaba.cloudgroupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
- dependency>
第四步: 在order-service和user-service微服务的application.yml里面,注释掉eureka地址,添加nacos地址
- # 因为nacos是spring的配置,所以要写在spring配置的下面
- cloud:
- nacos:
- server-addr: localhost:8848
配置完后user-service的yml文件如下
- server:
- port: 8081
- spring:
- datasource:
- url: jdbc:mysql://localhost:3306/cloud_user?useSSL=false
- username: root
- password:
- driver-class-name: com.mysql.jdbc.Driver
-
- application:
- # user的服务名称。也就是这个user-service注册到Eureka之后,这个user-service会叫什么名字
- name: UserService
- # 因为nacos是spring的配置,所以要写在spring配置的下面
- cloud:
- nacos:
- server-addr: localhost:8848
-
- mybatis:
- type-aliases-package: cn.itcast.user.pojo
- configuration:
- map-underscore-to-camel-case: true
- logging:
- level:
- cn.itcast: debug
- pattern:
- dateformat: MM-dd HH:mm:ss:SSS
-
- #eureka:
- # client:
- # service-url:
- # # eureka的服务地址。如果有多个的话,逗号隔开。也就是把当前这个user-service微服务注册给哪个Eureka
- # defaultZone: http://localhost:8686/eureka
配置完后order-service的yml文件如下
- server:
- port: 8080
- spring:
- datasource:
- url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
- username: root
- password:
- driver-class-name: com.mysql.jdbc.Driver
- application:
- # order的服务名称。也就是这个order-service注册到Eureka之后,这个order-service会叫什么名字
- name: OrderService
- # 因为nacos是spring的配置,所以要写在spring配置的下面
- cloud:
- nacos:
- server-addr: localhost:8848
-
- mybatis:
- type-aliases-package: cn.itcast.user.pojo
- configuration:
- map-underscore-to-camel-case: true
- logging:
- level:
- cn.itcast: debug
- pattern:
- dateformat: MM-dd HH:mm:ss:SSS
-
- #eureka:
- # client:
- # service-url:
- # # eureka的服务地址。如果有多个的话,逗号隔开。也就是把当前这个order-service微服务注册给哪个Eureka
- # defaultZone: http://localhost:8686/eureka
- ribbon:
- eager-load:
- enabled: true # 开启饥饿加载
- # 指定对UserService这个服务开启饥饿加载
- #UserService是你注册到Eureka时的服务名称。如果有多个服务需要做饥饿加载,就-往下写
- clients:
- - UserService
-
第五步: 服务注册,启动order-service和user-service微服务。浏览器输入访问地址
http://10.104.15.48:8848/nacos/index.html#/serviceManagement?dataId=&group=&appName=&namespace=&pageSize=&pageNo=

第六步: 服务发现。浏览器输入http://localhost:8080/order/101,多次访问。查看OrderService是否能正常请求UserService并拿到数据。查看负载均衡


可以看到id为2、3的是8081端口返回的;id为1、4的是8082端口返回的。有做负载均衡
概念
容灾系统是指在相隔较远的异地,建立两套或多套功能相同的IT系统,互相之间可以进行健康状态监视和功能切换,当一处系统因意外(如火灾、地震等)停止工作时,整个应用系统可以切换到另一处,使得该系统功能可以继续正常工作。容灾技术是系统的高可用性技术的一个组成部分,容灾系统更加强调处理外界环境对系统的影响,特别是灾难性事件对整个IT节点的影响,提供节点级别的系统恢复功能
服务跨集群调用问题的方案
上面学习了集群的分级存储模型,那怎么在代码上配置集群属性呢,下面就来学习
浏览器查看集群属性的信息,点击UserService服务的详情
跨集群部署的具体操作如下
第一步: 在复制出一个UserApplication3实例,端口为8283。此时我们就有三台服务名称为UserService的实例

分别修改这三台实例的application.yml实现把UserApplication、UserApplication2放到杭州集群,把UserApplication3放到上海集群,来模拟跨集群部署
首先配置user-service的application.yml文件如下,把集群设置为HZ(意为杭州),然后启动UserApplication和UserApplication2工程
- spring:
- # 要写在spring:属性下
- cloud:
- nacos:
- # nacos 服务地址
- server-addr: localhost:8848
- # 跨集群部署
- discovery:
- # 自定义集群名称。注意不能使用中文,我下面截图使用中文在启动时就报错了,大家记得用英文
- cluster-name: HZ
然后配置user-service的application.yml文件如下,把集群设置为SH(意为上海),然后启动UserApplication3工程
- spring:
- # 要写在spring:属性下
- cloud:
- nacos:
- # nacos 服务地址
- server-addr: localhost:8848
- # 跨集群部署
- discovery:
- # 自定义集群名称。注意不能使用中文,我下面截图使用中文在启动时就报错了,大家记得用英文
- cluster-name: SH
第四步: 测试。浏览器访问
http://10.104.15.48:8848/nacos/index.html#/serviceDetail?name=UserService&groupName=DEFAULT_GROUP

上面只是把user-service微服务(内含三个实例)部署成了两个集群,我们需要实现的是如何在order-service微服务去向user-service微服务发送请求,远程调用user-service微服务时,优先选择本地集群(相对而言),如果order-service是hangzhou集群,那么 '本地集群' 就是hangzhou集群,也就是order-service此时会远程向user-service的hangzhou集群发送请求,而不会向user-service的shanghai集群发送请求。如何实现,如下
第一步: 由于order-service还没有配置集群属性,所以我们先要给order-service集群配置集群属性。在order-service微服务的application.yml添加如下,然后重启OrderService
- spring:
- # 要写在spring:属性下
- cloud:
- nacos:
- # nacos 服务地址
- server-addr: localhost:8848
- # 跨集群部署
- discovery:
- # 自定义集群名称
- cluster-name: HZ

第二步: 根据集群,重新启动user-service微服务(如果你已经启动了就不用重启)
到这里,可以明确OrderService的本地集群是HZ,UserService有三个实例,UserApplication和UserApplication2的本地集群是HZ,UserApplication3的本地集群是SH
第三步: 浏览器访问order-service微服务,去请求user-service微服务的数据,请求多次。看一下请求的是user-service微服务的哪个实例(有三个实例)



此时三个实例都会接受OrderService的请求,依然访问策略依旧采用轮循方案,那么我们想要优先访问同集群的实例?可以进行如下配置
修改order-service中的application.yml,设置负载均衡的IRule为NacosRule,这个规则优先会寻找与自己同集群的服务。也就是让OrderService优先向集群为HZ的user-service实例发送请求
- # Nacos的负载均衡策略,优先向本地集群发送请求,注意UserService是你本地集群对应的服务名称,也就是注册到注册中心时的服务名称
- UserService:
- ribbon:
- # 负载均衡规则为NacosRule
- NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
添加后的order-service中的application.yml如下
- server:
- port: 8080
- spring:
- datasource:
- url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
- username: root
- password:
- driver-class-name: com.mysql.jdbc.Driver
- application:
- # order的服务名称。也就是这个order-service注册到Eureka之后,这个order-service会叫什么名字
- name: OrderService
- # 因为nacos是spring的配置,所以要写在spring配置的下面
- cloud:
- nacos:
- server-addr: localhost:8848
- discovery:
- cluster-name: HZ
-
- mybatis:
- type-aliases-package: cn.itcast.user.pojo
- configuration:
- map-underscore-to-camel-case: true
- logging:
- level:
- cn.itcast: debug
- pattern:
- dateformat: MM-dd HH:mm:ss:SSS
-
- # Nacos的负载均衡策略,优先向本地集群发送请求,注意UserService是你本地集群对应的服务名称,也就是注册到注册中心时的服务名称
- UserService:
- ribbon:
- # 负载均衡规则为NacosRule
- NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
-
- #eureka:
- # client:
- # service-url:
- # # eureka的服务地址。如果有多个的话,逗号隔开。也就是把当前这个order-service微服务注册给哪个Eureka
- # defaultZone: http://localhost:8686/eureka
- ribbon:
- eager-load:
- enabled: true # 开启饥饿加载
- # 指定对UserService这个服务开启饥饿加载
- #UserService是你注册到Eureka时的服务名称。如果有多个服务需要做饥饿加载,就-往下写
- clients:
- - UserService
-
重启OrderService,多次访问,看IDEA控制台信息
http://localhost:8080/order/105


这里做了8次请求访问,查看控制台,UserApplication3即集群地在SH的控制台无任何日志信息
即优先调用了HZ的集群中的实例
实现了让OrderService优先访问本地集群的UserService实例,此时OrderService服务的负载均衡策略就是在集群上,使用随机负载均衡
注意: UserService服务有三个实例,其中有两个实例的集群是跟OrderService服务是一样的,这两个实例我们称为是OrderService服务的本地集群。当OrderService服务的本地集群全部宕机时,此时OrderService服务才会向非本地集群发送请求,也就是此时UserService服务的集群为SH的实例才会生效。虽然是生效了访问成功,但是OrderService服务的控制台会报一个警告: "在UserService服务里面发生了一次跨集群访问,原本访问的集群是HZ,实际访问的集群是SH"
总结:
如果在配置同集群优先,没生效,可能是我们order-service启动类中配置的负载均衡规则为随机的RandomRule没有注释,注释掉即可
- // /**
- // * 配置负载均衡规则为随机
- // * 注入spring容器
- // * @return
- // */
- // @Bean
- // public IRule randomRule(){
- // return new RandomRule();
- // }
注意下面的是在上面的基础上接上去的,所以OrderService和UserService不需要关闭,保持运行即可
上面我们已经学了完整的多集群部署,但是,实际部署中会出现如下的场景:
由于服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求
解决方法就是使用Nacos提供的权重配置,就可以实现控制访问频率。权重越大,则访问频率越高
权重的取值范围是在0~1
具体操作如下
第一步: 浏览器访问。进行权重修改
http://192.168.127.1:8848/nacos/index.html#/serviceManagement?dataId=&group=&appName=&namespace=



第二步: 验证请求是否能被权重控制。浏览器访问order-service微服务,去请求user-service微服务的数据,请求10次


思考:如果把权重设置为0呢?
那这个服务就不会被访问
权重为0的使用场景: 如果要对某个实例进行版本升级,我们就不需要对这个实例进行重启,可以逐渐减低服务权重直至把这个实例的权重降为0。也叫降权重启(或灰度重启),升级完后再把权重调整回去,用户没有任何感知
Nacos首先是注册中心,而且还是数据中心,Nacos为了做数据和服务的管理,就有了一个环境隔离的概念。环境隔离最重要的就是namespace,也叫命名空间。Nacos中服务存储和数据存储的最外层都是一个名为namespace的东西,用来做最外层隔离。在namespace内部有一个group属性,作用是同一个namespace里面的多个东西,可以进行分组。group属性内部就是Service/Data,也就是具体的服务或数据。我们学的是隔离Service服务,不对隔离Data进行深入学习
Service里面的是集群,集群里面的是实例。环境隔离的本质就是对不同的服务进行隔离
我们可以把业务相关度比较高(例如订单服务和支付服务)的服务放到同一个Group组
具体操作如下
第一步: 浏览器访问。创建命名空间
http://10.104.15.48:8848/nacos/index.html#/serviceManagement?dataId=&group=&appName=&serverId=&namespace=




第二步: 把实例添加进刚刚创建的dev命名空间。修改order-service微服务的application.yml,添加namespace命名空间,值为刚才创建的dev命名空间的ID
- spring:
- # 要写在spring:属性下
- cloud:
- nacos:
- server-addr: localhost:8848
- discovery:
- cluster-name: HZ
- namespace: d8ec5ecb-2268-4551-ac2d-f08953292b28
第三步: 重新启动OrderService服务
第四步: 浏览器访问,查看dev命名空间是否有OrderService服务实例
http://10.104.15.48:8848/nacos/index.html#/configurationManagement?dataId=&group=&appName=&serverId=&namespace=&pageSize=&pageNo=

第五步: 这样分组隔离有什么用呢?作用: 此时OrderService服务是无法向UserService访问发送请求,因为这俩服务已经被隔离了

总结:
namespace用来做环境隔离
每个namespace都有唯一id
不同namespace下的服务不可见

什么是临时实例,什么是非临时实例。可在服务里面的application.yml设置
- spring:
- # 要写在spring:属性下
- cloud:
- nacos:
- server-addr: localhost:8848
- discovery:
- ephemeral: false # 设置为非临时实例
例如把OrderService服务设置为非临时实例,User-service服务不设置(默认是临时实例)

启动order-service,打开nacos控制台,可以看到order-service为非临时实例
临时实例的特点: 当服务或服务里面的某个实例出现问题时,注册中心就会把出问题的剔除
非临时实例的特点: 当服务或服务里面的某个实例出现问题时,注册中心不会把出现问题的剔除掉,注册中心会一直主动询问直到问题恢复

这里我们把order-service停止
打开控制台
总结:
一、Nacos和Eureka共同点
二、Nacos和Eureka不同点