【分布式】一文搞懂SpringCloudAlibaba - (二)注册中心 - Nacos

【注册中心】

注册中心

    分布式开发过程中要管理众多的服务也就是服务治理,管理服务与服务之间的依赖关系,实现服务调用、负载均衡、服务容错、以及服务的注册与发现。如果微服务之间存在调用依赖,就需要得到目标服务的服务地址,也就是微服务治理的服务发现。要完成服务发现,就需要将服务信息存储到某个载体,载体本身即是微服务治理的服务注册中心,而存储到载体的动作即是服务注册。
    在 RPC/HTTP 远程调用过程中,服务与服务之间依赖关系非常大,服务 URL 地址管理非常复杂,所以这时候需要对我们服务的 URL 实现治理。通过服务治理可以实现服务注册与发现、负载均衡、容错等。每次调用该服务如果地址直接写死的话,一旦接口发生变化的情况下,这时候需要重新发布版本才可以接口调用地址,所以需要一个注册中心统一管理我们的服务注册与发现。

常见注册中心对比

image.png

CAP 理论

    CAP 理论是分布式系统的三个指标。指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。这三个要素最多只能同时实现两点,不可能三者兼顾。而由于网络硬件肯定会出现延迟丢包等问题,所以分区容错性是我们必须需要实现的。所以我们只能在一致性和可用性之间进行权衡。

  • 一致性(C): 在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
  • 可用性(A): 在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
  • 分区容忍性(P): 以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在 C 和 A 之间做出选择。

CAP 理论不能同时满足的原因

  • CP 满足的情况下,A 不能满足的原因: 若要满足一致性(C)就需要在多个分布式节点之间进行数据同步,在数据同步完成之前整个系统都将不可用。节点数量越多分区容错性(P)越好,同时数据同步所耗费的时间自然也就越长,从而无法在有限的时间内完成请求响应,导致可用性(A)不能满足。
  • CA 满足的情况下,P 不能满足的原因: 若要满足一致性(C)就需要在多个分布式节点之间进行数据同步,在数据同步完成之前整个系统都将不可用。需同步的节点数量越多,数据同步所需耗费的时间越长,可用性(A)也越差。若要同时保证可用性(A),那么需同步的节点数量就需要尽量减少,从而导致分区容错性(P)无法满足。
  • AP 满足的情况下,C 不能满足的原因: 节点的数量越多,分区容错性(P)越好,节点间数据同步所需耗费的时间越长,若要在有限的时间内完成请求响应即保证可用性(A),那么数据就可能不能及时地同步到其他节点,从而无法保证节点间的数据一致性(C)。

CAP 理论满足情况

    在分布式系统中分区容错性(P)肯定要满足,所以只能在 CA 中二选一,  没有最好的选择,只有更适合的,我们需要根据自己的业务场景来进行架构设计。

  • Zookeeper: CP 设计,保证了一致性,集群搭建的时候,某个节点失效,则会进行选举新的 Leader,或者半数以上节点不可用,则无法提供服务,因此可用性(A)没法满足。
  • Eureka: AP 设计,无主从节点,一个节点挂了,自动切换其他节点继续使用,去中心化,但数据一致性(C)不满足。

Nacos

  Nacos 是一个更易于构件云原生应用的动态服务发现、服务管理、配置管理和消息驱动平台。即注册中心 + 配置中心 + 消息驱动。代替 Eureka + Config + Bus(Netflix 已经进入维护模式)

官方文档:https://sca.aliyun.com/
面试题:https://blog.csdn.net/golove666/article/details/137534990


【Nacos 注册中心】

SpringBoot 集成 Nacos 注册中心

  只需要引入 Nacos 相关的包,并且启动类上加@EnableDiscoveryClient 注解即可,默认请求 Nacos 地址为本机的 8848 端口。而且@EnableDiscoveryClient 在 Nacos 某版本后是不需要写了,但是写上也无妨。

<!-- ============================ pom.xml ============================ -->
<!-- Nacos注册中心 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
# ============================ application.yml ============================
spring:
  application:
    # 服务名
    name: server-a
  cloud:
    nacos:
      discovery:
        # Nacos服务端地址
        server-addr: http://127.0.0.1:8848/

Nacos 页面信息

  1. 命名空间: 常用于区分不同的环境(开发、测试、生产)。
  2. 服务名: 就是各个客户端注册到注册中心的服务名称。
  3. 分组: 命名空间下更细粒度的分类。
  4. 元数据: 就是任意的 key-value 键值对。
  5. 保护阈值: 可以配置成 0-1 之间的小数,当(所有实例/健康实例<保护阈值)的时候,服务也会被分发到不健康的实例上,防止健康的实例压力过大。【基本不用,后续使用 Sentinal 进行服务保护】
image.png

Nacos 客户端其他配置

  基本上 Nacos 在注册中心上的内容都体现在配置上,所以详细内容请查看下方代码块即可。

spring:
  cloud:
    nacos:
      discovery:
        # Nacos注册中心地址【默认127.0.0.1:8848】
        server-addr: 127.0.0.1:8848
        # Nacos账号【默认nacos】
        username: nacos
        # Nacos密码【默认nacos】
        password: nacos
        # 命名空间【默认public】
        namespace: dev
        # Nacos分组名【默认DEFAULT_GROUP】
        group: imomei_group
        # 网卡名。【当IP未配置时,注册的IP为网卡对应的IP地址。】
        # 一般都使用spring.application.cloud.inetutils.preferred-networks=172.18.40进行配置注册IP选择前缀
        network-interface: xxx
        # 本服务注册到Nacos的IP地址【默认自动识别】
        ip: xxx
        # 本服务注册到Nacos的端口【默认自动识别】
        port: xxx
        # 是否临时实例。设置为永久实例,即使宕机也不会从列表中删除该服务【默认为true不永久】
        ephemeral: false
        # 权重,仅当Ribbon负载均衡策略配置为根据权重才生效。【默认为1】
        weight: 2
        # Nacos集群名称,仅当Nacos是集群部署这个配置才有用且必须。
        cluster-name: xxx

【Nacos 服务端部署】

Linux 部署 Nacos 服务端(单机)

  1. 新建一个实例名为 nacos 的数据库,并执行 nacos/conf 下的 nacos-mysql.sql 文件创建表。
  2. 打开 conf 下的 application.properties 文件,修改数据库连接(如果不修改数据库的连接,默认存在内存中)
  3. 如果不是部署 nacos 集群,则将模式修改为单机模式。打开 bin/startup.cmd 或者 startup.sh 文件,将 MODE 从 cluster 改为 standalone
  4. 双击 bin/startup.cmd 文件,启动成功。打开浏览器访问:http://localhost:8848/nacos/index.html
  5. 默认账号密码:nacos/nacos
image.png
# ==================================== 修改application.properties ====================================
# 数据库类型
spring.datasource.platform=mysql
# 连接地址(要把.0去掉)
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos...
# 账号(要把.0去掉)
db.user=root
# 密码(要把.0去掉)
db.password=root
# ==================================== 修改startup.cmd/sh ====================================
set MODE="standalone"

Docker 部署 Nacos 服务端(单机)

docker run -d \
  -e MODE=standalone \
  --privileged=true \
  -e JVM_XMS=128m \
  -e MODE=standalone \
  -e JVM_XMX=128m \
  -e SPRING_DATASOURCE_PLATFORM=mysql \
  -e MYSQL_SERVICE_HOST=182.92.158.133 \
  -e NACOS_CORE_AUTH_ENABLED=false \
  -e MODE=standalone \
  -e MYSQL_SERVICE_PORT=3306 \
  -e MYSQL_SERVICE_USER=root \
  -e MYSQL_SERVICE_PASSWORD=cqz19960117 \
  -e MYSQL_SERVICE_DB_NAME=nacos \
  -e TIME_ZONE='Asia/Shanghai' \
  -p 8848:8848 -p 9848:9848 -p 9849:9849 \
  --name nacos --restart=always f151dab7a111

Nacos 服务端集群搭建

  1. 如同单机版一样,修改数据库相关配置,端口区分开即可。startup 启动脚本需要改成是 cluster,并且建议修改下脚本,降低启动内存占用。
  2. conf/cluster.conf.exmple 文件修改为 cluster.conf 并且内部配置上所有 Nacos 节点的 IP 端口。
  3. 使用 Nginx 对 Nacos 进行负载均衡。
  4. NacosClient 的配置文件修改为 nginx 暴露的端口,我这里服务是 8843、8846、8849,nginx 开放端口还是保持为 8848。(端口不能离太近,要不会占用下一个,所以离远点)
# ---------------------------------------------- cluster.conf -------------------------------------
# 集群各个IP和端口
127.0.0.1:8843
127.0.0.1:8846
127.0.0.1:8849
# ---------------------------------------------- nginx.conf -------------------------------------
# 通过Nginx对Nacos多个服务器进行负载均衡
upstream nacoscluster{
    server 127.0.0.1:8843;
    server 127.0.0.1:8846;
    server 127.0.0.1:8849;
}
server {
    listen       8848;
    server_name  127.0.0.1;
    location /nacos/ {
      proxy_pass http://nacoscluster/nacos/;
    }
}
# ---------------------------------------------- 客户端yml -------------------------------------
spring:
  cloud:
    nacos:
      # Nacos注册中心地址(集群情况写Nginx的IP端口就可以)
      server-addr: 127.0.0.1:8848

【Nacos 源码分析】

Nacos 客户端注册源码分析

  1. AbstractAutoServiceRegistration类实现了ApplicationListener<WebServerInitializedEvent>,会在SpringBoot项目启动成功之后调用onApplicationEvent()方法。
  2. onApplicationEvent()中调用了start()方法。
  3. start()中间有一行是调用了register()方法。
  4. register()最终执行的就是NacosServiceRegistry类中的register()方法
@Override
public void register(Registration registration) {
  NamingService namingService = namingService();
  String serviceId = registration.getServiceId();
  String group = nacosDiscoveryProperties.getGroup();
  // 设置参数(从配置中获取)
  Instance instance = getNacosInstanceFromRegistration(registration);
  // 初始化注册
  namingService.registerInstance(serviceId, group, instance);
}
  1. register()中初始化了一些配置的参数,然后初始化注册器。
  2. 注册器中调用registerService()向 Nacos Server 端发送请求。具体请求方法为reqApi()
public String callServer(String api, Map<String, String> params, Map<String, String> body, String curServer, String method) throws NacosException {
  // 这里就是请求注册
  HttpRestResult<String> restResult = nacosRestTemplate.exchangeForm(url, header, Query.newInstance().initParams(params), body, method, String.class);
  end = System.currentTimeMillis();
  MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode())).observe(end - start);
  if (restResult.ok()) {
      return restResult.getData();
  }
  if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {
      return StringUtils.EMPTY;
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值