前面已经学习了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版本
com.alibaba.cloud
spring-cloud-alibaba-dependencies
2.2.5.RELEASE
pom
import
第二步: 在order-service和user-service微服务的pom.xml里面,注释掉原有的eureka依赖
第三步: 在order-service和user-service微服务的pom.xml里面,添加nacos的客户端依赖
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
第四步: 在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集群,也就是user-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不同点