Nacos 是阿里的产品,现在是 SpringCloud 中的一个组件。它的功能要比 Eureka 更加丰富,在国内比较受欢迎。
百度网盘下载链接:https://pan.baidu.com/s/1XLn7hGp2bHBx7ICvKELtzQ?pwd=dju6
Nacos 官网下载:https://nacos.io/
① 点击前往 Github
Github 页面打不开的可以下一个加速器,我用的 Watt Toolkit, 很好用!
② 点击界面右侧的 releases
③ 点击 Tags 选择一个版本下载
④ 点击 download 之后往下滑,这里我们选择第二个 Windows 版本的开始下载
⑤ 下载完之后把它解压到一个非中文的目录中
⑥ 打开 bin 目录,双击 startup.cmd 文件即可启动 nacos,但是默认情况下 nacos 是以集群启动的,导致启动不成功。所以这里可以通过 startup.cmd -m standalone 命令来启动 nacos,standalone 就是单机启动的意思
⑦ 复制以下链接到浏览器打开,即可访问 Nacos
⑧ 默认账号和密码都是 nacos
对于项目的结构,参照本专栏的第一篇文章即可,我们依然在这个项目中进行修改。
传送门,点击这里
源码也打包好了:https://pan.baidu.com/s/1Zk0F699xABs3AmPbtr7DQA?pwd=po2e
① 父工程中引入如下依赖
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.2.9.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-loadbalancerartifactId>
<version>3.1.7version>
dependency>
② 子工程中引入如下依赖
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
userserver 和 orderserver 同理!
spring:
cloud:
nacos:
server-addr: localhost:8848 #nacos服务地址
启动类上添加 @EnableDiscoveryClient 注解。
将所有与 Eureka 相关的代码都删掉,启动项目前先启动 nacos 控制台!
启动项目的时候我发现报错了,应该是版本问题,我们之前使用的 SpringBoot 和 SpringCloud 的版本都很低,而 SpringCloud Alibaba 的低版本已经停止维护了,迫不得已,只能对 SpringBoot 和 SpringCloud 升级。对应版本如下图所示:
① 实际项目中肯定不止两个微服务,一个一个启动太麻烦,所以我们试着一键启动所有微服务
Alt + 8,然后 Ctrl 加鼠标左键选中所有想要启动的微服务,点击左侧的绿色三角形启动,前提是这些启动类之前都运行过一次。
② 项目启动成功后,再回到 nacos 的控制台,可以看到这两个微服务都已经注册进来了,还可以点击详情查看服务的具体信息
③ 服务注册成功之后,就可以访问了
当 orderserver 去请求 userserver 时,我们拉取到的是一个 userserver 的服务列表,然后对列表里的服务做负载均衡。
也就是说一个请求可被多个服务实例所等待,最终我们是要从这多个实例中选择一个出来,去处理请求。为了尽可能地减少延迟,Nacos 服务采取分级存储模型,一级是服务,二级是集群,三级是实例。
服务调用尽可能选择本地集群的服务,因为跨集群调用的延迟较高,只有当本地集群不可访问时,才去访问其它集群。
① 右键 UserServerApplication → Copy Configuration
② 自定义实例名称 → 点击 modify options → Program arguments
③ 配置端口号,不能重复,–server.port=8083
④ 可以按照同样的方法多启动几个
⑤ 点进 Nacos 控制台看一下,这里的实例数已经变成 4,集群名称是默认的 DEFAULT
① orderserver 和 userserver 都配置
spring:
cloud:
nacos:
discovery:
cluster-name: SX #集群名称
② 其中对于不同的 userserver 服务,先以这个集群开启一部分服务,然后修改集群名称,再开启另一部分服务,模拟多机房多集群场景,如下三个服务已经启动成功
③ 修改集群名称,并启动剩余的两个服务,观察 Nacos 控制台
④ 去浏览器发送请求,经过多次试验,我们发现它并没有优先选择本地集群的服务去调用,而是以轮询的方式调用服务。其实这里还需要最后一步配置,就是修改负载均衡的规则
SpringCloud Nacos 2021 版本以下,通过如下方式配置:
#优先选择同一集群
userserver:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
SpringCloud Nacos 2021 版本以后就移除了 Ribbon,可以通过下面的方式配置负载均衡:
spring:
cloud:
loadbalancer:
nacos:
enabled: true
⑤ 再次启动服务发送请求的时候,就可以看到我们调用到的服务全部都来自同一集群,只有当本地集群上的服务都挂掉的时候,才去调用其他集群中的服务
默认采用轮询的方式选择服务实例,配置了 Nacos 负载均衡策略后会优先选择同一集群的服务列表进行调用,只有当本地集群挂掉之后才去寻找其它集群,最后,在集群内部再采用随机负载均衡策略来挑选实例!
实际部署中会出现这样的问题:
服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,而我们希望性能好的机器可以承担更多的用户请求。
Nacos 给我们提供了权重配置来控制访问频率,权重越大则访问到的频率就越高。
实例的权重控制:
① Nacos 控制台可以设置实例的权重值,一般在 0 ~ 1 之间;
② 同集群内的多个实例,权重越高被访问的频率就越高;
③ 权重设置为 0 则完全不会访问。
权重为 0 时压根就不会被访问,我们可以利用这个特性来进行版本的升级。版本升级就势必要停掉服务,但是服务在运行的时候突然被重启,这肯定会影响到线上业务呀,所以说我们是不能去随便重启服务的。
其实在版本升级的时候,我们可以先把其中一个服务的权重调成 0,此时该服务就不再参与处理用户请求,因为同一个业务的服务器不止这一个,所以用户是不会有任何感知的,这个时候我们可以对服务做版本的升级,升级完成之后可以把该服务的权重调小一点,让少数用户进来做一个线上测试,如果没什么问题我们就可以扩大比例,依次升级,在这个过程中用户是无感知的,可以做到平滑升级。
Nacos 是一个注册中心,同时它也是一个数据中心。在服务存储和数据存储的最外层都有一个叫 namespace 的东西,用来做最外层隔离,即环境隔离。
在实际生产中不可能只有一个环境,比如会有开发环境、测试环境等,这些环境之间当然是需要隔离的,环境的隔离就通过配置 Namespace 实现。Namespace 内部有不同的 Group,Group 内部又有具体的服务或数据,服务内有集群,集群再往下就是实例。(一般情况下也不会去配 Group)
① 点击 Nacos 控制台的命名空间,可以看到 Namespace 默认的命名空间是 public
② 点击新建命名空间,填写命名空间名和描述
③ 配置服务的命名空间,注意配置的 namespace 值正是我们刚刚创建的命名空间的ID
spring:
cloud:
discovery:
namespace: 6f4f54d7-6728-486d-9d42-7a6aa85cefa3 #dev环境
④ 我这里只配置了 orderserver 的 namespace,我们重启一下再打开 Nacos 控制台,可以看到 dev 命名空间里面多了一个 orderserver
⑤ 此时 orderserver 和 userserver 已经是两个世界的人了,当你再次请求服务的时候,发现它报错了
不同 namespace 下的服务不可见,所以服务之间要想正常访问,就必须得把它们放在相同的环境下!
跟 Eureka 一样,服务提供者在启动的时候就会向 Nacos 注册自己的服务信息,而服务消费者到时候直接从 Nacos 上拉取服务。当然,请求不止一次,不可能每次都去注册中心拉取,所以 Nacos 也提供了缓存机制,这个功能其实在 Eureka 里面就已经有了,它会将拉取到的服务列表做一个缓存,提高访问速度,同时为避免服务已经挂掉,消费者每隔 30 秒就向 Eureka 发起一次请求,重新拉取服务列表做一次更新,最终在拉取到的服务列表里面做负载均衡,选择一个服务远程调用就可以了。
① 与 Eureka 不同的是,Nacos 将服务的提供者划分成临时实例和非临时实例,在默认情况下都是临时实例。临时实例在做存活检测时采用的是心跳检测,这一点跟 Eureka 完全一致,服务提供者每隔一段时间就会向注册中心发送一个心跳证明自己还活着,当有一天没有心跳了,Nacos 就会将它直接从服务列表中剔除,当然 Nacos 的心跳频率比 Eureka 更快一点。
与之相对的是非临时实例,它是没有心跳的,那么它是如何进行存活检测呢?
非临时实例是由 Nacos 主动询问的,即使有一天该服务挂掉了,Nacos 也不会将其从列表中剔除,它会一直等待,等待服务恢复健康。 从这里我们可以看出,非临时实例的身价是相当高的。
**② 第二个不同点就是 Nacos 提供了主动推送变更消息的功能,时效性更好。**在 Eureka 中消费者拉取到的服务列表每隔 30 秒都会重新拉取一遍,但是恰好我的服务就在这 30 秒内挂掉呢?这个事情是会发生的。所以 Nacos 提供了主动推送变更消息的功能,既可以拉取服务又可以主动推送,当 Nacos 检测到某个服务挂掉了,它就会立马发送消息推送给消费者,告诉消费者:服务已变更请立即更新。
(1)共同点:
① 都支持服务注册和服务拉取;
② 都支持发送心跳的方式做健康监测。
(2)区别:
① Nacos 支持服务端主动监测提供者的状态,临时实例采用心跳模式,非临时实例采用主动检测模式;
② 临时实例心跳不正常会被剔除,非临时实例则不会被剔除;
③ Nacos 支持服务列表变更的消息推送模式,服务列表更新及时;
④ Eureka 集群采用 AP 方式,Nacos 集群默认采用 AP 方式,当集群中存在非临时实例时,采用 CP 模式。
AP 模式强调服务的可用性,而 CP 模式更强调数据的可靠性和一致性!
服务注册到 Nacos 时,可以选择临时实例或非临时实例,通过配置来修改,推荐使用默认的临时实例,避免给服务器造成太大压力。
spring:
cloud:
nacos:
discovery:
ephemeral: false #设置为非临时实例