服务注册与发现:Nacos为例
在现代微服务架构中,服务注册与发现中间件已经成为了一个重要的分布式系统协调工具。为什么我们需要这样一个工具?分布式系统需要有效和可靠的工具来管理配置数据、服务发现和协调。Nacos作为一体化服务发现与配置管理工具,扮演着服务注册与发现中间件的重要角色。本文将以Nacos为例,深入探讨服务注册与发现中间件的原理、功能和使用。
由于Nacos是国内产品,中文文档比较丰富,而且同时具备配置管理功能,因此在国内使用较多,故本篇文章中我们会Nacos来举例
服务注册与发现的基本原理
当我们实现一个微服务架构时,有许多不同的服务需要相互协作。而服务的动态性和规模的增长使得手动管理服务的地址和状态变得非常困难,为了管理这些服务就引入了服务注册中心的概念,而那些服务注册与发现中间件则是通过注册服务、发现服务、健康检查等基本原理来解决这个问题,我们做一个比喻:服务注册中心就像是给这些服务创建一个“目录”,让它们能够轻松地找到和联系(发现)对方:
- 服务注册: 想象一下,每个服务都像一个商家,当它启动时,就会在“目录”上注册自己的信息,比如服务的名称、地址和端口号。这样,其他服务就能够知道这个服务的存在。
- 服务发现(订阅): 现在,如果一个服务需要与其他服务通信,它可以去“目录”查找目标服务的信息。这就像在目录中查找电话号码一样,只不过这里是查找服务的网络地址。服务发现使得服务能够动态地找到彼此,而不需要硬编码固定的地址。
- 健康检查: 为了确保“目录”中的信息是最新的,系统还会定期检查服务的健康状态。如果一个服务出现了问题,就会被标记为不可用,其他服务就不会再尝试联系它,以确保整个系统的稳定性。
注册中心、服务提供者、服务消费者三者间关系如下:
上图共涉及到以下 3 个角色:
- 服务注册中心(Register Service):它是一个 Nacos Server,可以为服务提供者和服务消费者提供服务注册和发现功能。
- 服务提供者(Provider Service):它是一个 Nacos Client,用于对外服务。它将自己提供的服务注册到服务注册中心,以供服务消费者发现和调用。
- 服务消费者(Consumer Service):它是一个 Nacos Client,用于消费服务。它可以从服务注册中心获取服务列表,调用所需的服务。
具体流程如下:
- 服务注册:
- 服务提供者在启动时向注册中心注册自己的服务信息,包括服务名、IP地址、端口等。
- 这个注册过程可以在服务启动时进行,并且也可以定期地进行心跳更新。
- 服务订阅:
- 调用者可以向注册中心订阅特定的服务,以获取服务对应的实例列表。
- 实例列表可能包括同一服务的多个实例,用于实现负载均衡。
- 负载均衡:
- 调用者通过负载均衡算法从实例列表中选择一个实例来发起远程调用。
- 常见的负载均衡算法包括轮询、随机、加权轮询等。
- 健康状态检查:
- 服务提供者定期向注册中心发送心跳请求,报告自己的健康状态。
- 如果注册中心长时间未收到某个实例的心跳,认为该实例可能宕机,将其从服务的实例列表中剔除。
- 新实例启动:
- 当服务提供者启动新的实例时,新实例会发送注册服务请求,将其信息记录在注册中心的服务实例列表中。
- 通知机制:
- 当注册中心服务列表发生变更时,它会主动通知订阅该服务的微服务,以更新本地服务列表。
- 通知可以通过长连接、轮询等方式实现。
Nacos注册中心
目前开源的服务注册与发现中间件有很多,国内比较常见的有:
特性/工具 | Nacos | Zookeeper | etcd |
---|---|---|---|
设计理念 | 一体化服务发现、配置管理、动态DNS | 分布式协调服务 | 分布式键值存储系统 |
主要特性 | 多功能一体化、多语言支持、灰度发布 | 一致性、分布式锁、Watcher机制 | 强一致性、分布式事务、Raft协议 |
一致性要求 | 相对较弱 | 强一致性 | 强一致性 |
使用复杂度 | 相对简单 | 相对复杂 | 相对复杂 |
主要用途 | 服务发现、配置管理、动态DNS | 分布式协调、服务注册与发现 | 配置管理、服务注册与发现 |
对比总结:
- 一体化 vs. 分布式协调: Nacos提供了一体化的服务发现和配置管理,而Zookeeper和etcd更侧重于分布式协调和数据存储。
- 功能丰富性: Nacos提供了更多的功能,包括服务发现、配置管理、动态DNS等,而Zookeeper和etcd更专注于分布式协调。
- 一致性要求: 如果系统对一致性要求较高,Zookeeper和etcd是更好的选择,而如果需要一体化的服务发现和配置管理,Nacos是一个更全面的解决方案。
- 使用复杂度: Nacos的使用较为简单,而Zookeeper和etcd在分布式系统的基础设施层面提供更多细粒度的控制,因此可能相对复杂。
Nacos的基本部署
以Nacos 2.1.1举例
Release 2.1.1 (Aug 8th, 2022) · alibaba/nacos (github.com)
简易部署
最简易版方式安装,主打的就是有问题铲了重装。
docker run \
-d -p 8848:8848 \
-p 9848:9848 \
--name nacos2 \
-e MODE=standalone \
-e TIME_ZONE='Asia/Shanghai' \
nacos/nacos-server:v2.1.1
运行成功,稍等几秒启动时间,浏览器输入 http://localhost:8848/nacos/index.html
查看控制台。
注:初始账户密码均为 nacos,只要进入了页面就代表启动成功了
但这样的话有一点小瑕疵,nacos所有元数据都会保存在容器内部。倘若容器迁移则nacos源数据则不复存在,所以通常我们通常会将nacos元数据保存在mysql中,请看下面的小认真部署:
小认真部署
首先我们要准备MySQL数据库表,用来存储Nacos的数据。
nacos/config/src/main/resources/META-INF/nacos-db.sql at 2.1.1 · alibaba/nacos (github.com)
将SQL文件导入到你Docker中的MySQL容器
接下来运行 nacos 的 docker 安装命令
下列参数请自行设置
MYSQL_SERVICE_HOST
mysql的IP地址,在同一docker网络下,填容器名即可MYSQL_SERVICE_PASSWORD
- 挂载目录等不多赘述
docker run --name nacos -d --network west2_net -p 7744:8848 -p 8744:9848 -p 8745:9849 --privileged=true --restart=always -e MODE=standalone -e PREFER_HOST_MODE=hostname -e SPRING_DATASOURCE_PLATFORM=mysql -e MYSQL_SERVICE_HOST=mysql -e MYSQL_SERVICE_DB_NAME=db_nacos -e MYSQL_SERVICE_PORT=3306 -e MYSQL_SERVICE_USER=nacos -e MYSQL_SERVICE_PASSWORD=123456 -e TIME_ZONE='Asia/Shanghai' -v /home/nacos/logs:/home/nacos/logs nacos/nacos-server:v2.1.1
- 前面导入的sql文件已经包含了nacos的各个数据,无需再进行初始化。
-p 7744:8848 -p 8744:9848 -p 8745:9849
: 将容器的端口映射到宿主机的端口,分别为 7744:8848(Nacos控制台)、8744:9848 和 8745:9849。-e PREFER_HOST_MODE=hostname
: 使用主机名模式。-e SPRING_DATASOURCE_PLATFORM=mysql
: 使用MySQL作为数据库。-e MYSQL_SERVICE_HOST=mysql -e MYSQL_SERVICE_DB_NAME=db_nacos -e MYSQL_SERVICE_PORT=3306 -e MYSQL_SERVICE_USER=nacos -e MYSQL_SERVICE_PASSWORD=123456
: 设置MySQL数据库相关的环境变量。
启动完成后,访问控制台就好啦,nacos控制台地址为:http://你的IP地址:7744/nacos/index.html
Docker Compose部署最新版
Nacos自2.2.2版本开始,在未开启鉴权时,默认控制台将不需要登录即可访问,同时在控制台中给予提示,提醒用户当前集群未开启鉴权。
以下为开启鉴权:
我们部署nacos的最新镜像版本,请根据对应版本找到对应的sql文件
nacos/config/src/main/resources/META-INF/nacos-db.sql at 2.3.0 · alibaba/nacos (github.com)
修改sql文件,在文件的第一行添加一行sql创建数据库
CREATE database if NOT EXISTS `nacos_config` default character set utf8mb4 collate utf8mb4_unicode_ci;
use `nacos_config`;
并将修改后的sql文件放入/data/docker/mysql/init.sql,作为docker容器初始化sql。
创建一个 docker-compose.yml 文件,内容如下:
下列参数请自行设置:
MYSQL_SERVICE_HOST=${SERVER_ip}
修改成服务器的ip- NACOS_AUTH_IDENTITY_KEY
- NACOS_AUTH_IDENTITY_VALU
- NACOS_AUTH_TOKEN 自定义密钥,推荐将配置项设置为Base64编码的字符串,且原始密钥长度不得低于32字符。
version: '3.9'
services:
mysql:
image: mysql:latest
container_name: mysql
hostname: mysql
restart: always
networks:
- west2_net
environment:
MYSQL_ROOT_PASSWORD: "123456"
ports:
- "13306:3306"
volumes:
- "/data/docker/mysql/data:/var/lib/mysql"
- "/data/docker/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql"
nacos-server:
image: nacos/nacos-server:latest
container_name: nacos-server
hostname: nacos-server
networks:
- west2_net
ports:
- "8848:8848"
- "9848:9848"
privileged: true
restart: always
environment:
- PREFER_HOST_MODE=hostname
- MODE=standalone
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=${SERVER_ip}
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_PORT=13306
- MYSQL_SERVICE_USER=root
- MYSQL_SERVICE_PASSWORD=123456
- MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
- NACOS_AUTH_IDENTITY_KEY=west2
- NACOS_AUTH_IDENTITY_VALUE=west2
- NACOS_AUTH_ENABLE=true
- NACOS_AUTH_TOKEN=MTQ3NmViZDctOTJiNC00MmZmLWJhNmItMjA4MzA3ZTUyYmZj
- JVM_XMS=125M
- JVM_XMX=125M
- JVM_XMN=50M
- JVM_MS=50M
- JVM_MMS=50M
depends_on:
- mysql
volumes:
- "/data/docker/nacos/logs:/home/nacos/logs"
networks:
west2_net:
driver: bridge
启动!
docker-compose up -d
查看日志
docker-compose logs -f
运行成功,稍等几秒启动时间,浏览器输入
http://对应ip:8848/nacos
查看控制台。账号密码默认为nacos。