从负载均衡到配置中心,Nacos内置功能一次讲清?

一、负载均衡

1.1.、服务下线

Nacos支持我们不对程序做如何的改变,直接对服务进行下线,操作如下

我们选择端口号为 9091 的服务器,进行下线,然后请求接口

再次点击上线后,9091服务器即可正常接收参数(注意:服务下线时程序仍在后台运行,只是注册中心暂无法远程调用该服务接口,我们仍可直接访问该接口)

1.2、权重配置

1.2.1、配置权重

当我们新注册一个服务器,并不清楚其性能如何,我们便想分配给新服务器较少的请求,以便观察其性能和稳定性,此时我们便可以通过配置权重操作来将请求按照不同的比重分配给不同的服务器

我们将9091服务器的权重改为0.1,9090和9092服务器的权重不作修改,仍为1,然后向订单服务发送多个请求,观察不同服务器的请求数量:

从上述结果可以观察到:虽然我们把9091服务器的权重值修改为0.1,但是该服务器的请求数量与我们预期的结果并不相符,即配置的权重并未生效

1.2.2、负载均衡策略

Spring Cloud LoadBalancer 组件本身已具备负载均衡配置能力,因此无法直接支持 Nacos 的权重属性配置。要启用 Nacos 的权重配置功能,需手动开启其负载均衡策略

如何解决MSE Nacos上修改服务实例的权重不⽣效问题_微服务引擎(MSE)-阿⾥云帮助中⼼https://help.aliyun.com/zh/mse/support/what-do-i-do-if-the-modified-weight-of-an-application-instance-does-not-take-effect-on-an-mse-nacos-instance 此处我们既然知道原因,在订单系统中开启负载均衡策略即可:

XML 复制代码
spring:
  cloud:
    loadbalancer:
      nacos:
        enabled: true
1.2.3、测试

我们再次发送20个请求后,发现,9091服务器只收到一个请求,说明负载配置成功

二、同集群优先访问

2.1、配置集群名称

我们为商品服务和订单服务配置集群名称:BJ

XML 复制代码
spring:
  cloud:
    nacos:
      discovery:
        cluster-name: BJ
XML 复制代码
-Dserver.port=9091 -Dspring.cloud.nacos.discovery.cluster-name=SH

重新运行服务器,观察集群情况:可以看到,服务器都按照配置的集群名称分到了不同的集群

2.2、负载均衡策略

同集群优先访问策略依然需要开启负载均衡策略(1.2.2已经配置过)

2.3、测试

配置完同集群优先访问策略后,9090服务器和订单服务都在BJ集群,而9091和9092服务器则在SH集群,我们在订单服务发送多个远程调用后发现,所有的请求都被同集群的9090服务器接收到了

如果我们对9090服务器进行下线操作,那么9091和9092便会接受来自BJ集群的请求

三、健康检查

3.1、两种检查机制

Nacos作为服务注册中心,需要实时掌握服务实例的健康状态,以确保服务调用方能够获得可靠的服务。Nacos提供了以下两种健康检查机制:

客户端主动上报机制

  • 客户端通过定期心跳上报的方式向Nacos服务端同步健康状态,默认心跳间隔为5秒
  • 若Nacos超过15秒未收到心跳,实例将被标记为不健康状态;30秒未收到心跳则自动移除该实例

服务端主动探测机制

  • Nacos服务端会主动探测客户端健康状态,默认探测间隔为20秒
  • 当健康检查失败时,实例会被标记为不健康状态但仍保留在注册中心

3.2、服务实例类型

Nacos的服务注册节点分为两种类型:临时实例永久实例

  • 临时实例 :当节点发生故障且超过设定时间后,系统会自动将其从服务列表中移除(默认注册类型)
  • 永久实例 :即使节点出现故障,系统仍会保留其在服务列表中,不会自动剔除

目前我们的三个节点均为临时实例,我们停掉9092服务器,观察Nacos会不会将其从服务列表移除:

可见,SH集群下的服务实例只剩下一个,那么我们再来测试永久实例,先来学习一下如何设置永久实例,配置以下信息即可

程序启动后发现错误:Current service DEFAULT_GROUP@@order-service is ephemeral service, can't register persistent instance,即当前这个服务为一个临时实例,不能注册为永久实例

原因 :Nacos会记录每个服务实例的IP地址和端口号。当检测到IP和端口均未发生变化时,Nacos不允许更改服务实例类型,例如从临时实例转为非临时实例,或反之

解决方案:

此时我们终止订单服务

  1. 停止Nacos服务
  2. 删除Nacos目录下的/data/protocol/raft文件夹,该文件夹存储了应用实例的元数据信息

四、环境隔离

4.1、创建NameSpace

默认情况下,所有服务都位于名为"public "的同一个命名空间中,我们先后创建开发环境测试环境 ,通常,环境之间无法直接通信,Nacos 通过 namespace(命名空间)机制实现环境隔离,不同命名空间下的服务相互不可见

4.2、配置NameSpace

可见 order-service 在 dev 命名空间下

4.3、测试远程调用

我们尝试调用商品服务发现:
观察日志:No instances available for product-service 没有可用的商品服务,因为商品服务全部在public命名空间下,不同的命名空间是不可见的,所以订单服务调用不了商品服务

我们修改商品服务的一个实例到dev环境下:

再次调用商品服务:

五、配置中心

当前项目的配置信息都直接写在代码中,这会带来以下问题:

  1. 修改配置时需要重新部署服务。在微服务架构下,一个服务可能部署了上百个实例,逐个部署不仅耗时费力,还容易出错

  2. 团队协作开发时,配置文件需要频繁修改,共用一个文件容易导致代码冲突

配置中心可以统一管理这些配置项,实现配置的集中查看、修改和删除,无需再逐个修改配置文件。这样既提高了工作效率,也降低了出错风险

服务启动时,系统会从配置中心自动获取配置项内容并完成初始化

当配置项发生变更时,微服务会实时接收通知并更新配置

5.1、添加配置

此处Data ID 为目标项目的名称,切配置内容格式目前仅支持:YAML 和 Properties

5.2、获取配置

5.2.1、引入依赖
XML 复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud 2020.*之后版本需要引⼊bootstrap-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
5.2.2、配置bootstrap.yml

微服务启动前需从 Nacos 获取配置信息,并与 application.yml 中的配置进行合并。为确保正常运行,必须在 bootstrap.yml 文件中配置 Nacos Server 地址(properties配置文件也可以)

XML 复制代码
spring:
  application:
    name: product-service
  cloud:
    nacos:
      config:
        server-addr: 公网IP+端口号

需要确保 spring.application.name 与 Nacos 配置管理的 Data ID 保持一致
同时,spring.cloud.nacos.config.server-addr应配置为 Nacos Server 的地址

5.2.3、读取配置项

注意 :上述配置的yaml文件经尝试,程序启动时报错:Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'nacos.config' in value "${nacos.config}"----Nacos,小奥奇暂时未找到原因,于是在Nacos配置管理中按上述内容新创了两个Properties格式的配置信息

java 复制代码
@RestController
public class NacosController {
    @Value("${nacos.config}")
    private String nacosConfig;

    @RequestMapping("/getConfig")
    public String getConfig(){
        return "从Nacos中获取配置项nacos.congig:"+nacosConfig;
    }
}

访问127.0.0.1:9090/getConfig,观察结果:

我们修改配置内容后,再次访问:

从图中可以看出,修改后的访问结果仍显示为修改前的配置内容。我们只需要在 nacosController 类上添加 @RefreshScope 注解即可实现配置热更新

如需读取其他命名空间的配置信息,需在bootstrap.yml文件中进行相应配置

复制代码
spring:
  cloud:
    nacos:
      config: namespace: 配置管理命名空间id