注册中心学习笔记整理
Eureka
核心概念
- 服务注册中心:Eureka Server 作为中心节点,维护所有服务实例的注册表(IP、端口、健康状态
- **客户端注册:**服务提供者(Eureka Client)启动时向 Server 注册自身信息,并通过心跳维持租约
- 服务发现:消费者通过 Server 获取可用服务列表,结合负载均衡策略调用服务
Eureka的安装与配置
安装步骤:
- 创建springboot项目,并且添加Spring Web
+
Eureka Server依赖 - 配置Eureka server(服务器)
yaml
# application.yml
server:
port: 8761
eureka:
client:
register-with-eureka: false # 不注册自身
fetch-registry: false # 不拉取注册表
service-url:
defaultZone: http://localhost:8761/eureka
- 启用服务端:启动类添加注解
@EnableEurekaServer
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- 运行项目,访问
http://localhost:8761
,你将看到Eureka Server的管理界面

客户端注册:
- 添加依赖:版本可以直接到https://mvnrepository.com/里面搜索添加,一定要兼容版本
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>版本</version>
</dependency>
- 配置客户端
yaml
# application.yml
spring:
application:
name: user-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
- 启动服务发现:启动类添加
@EnableDiscoveryClient
注解,在application启动类上面添加
java
package com.miracle.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* 启动类
*/
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient //在做远程调用的时候我们必须要激活discoverClient
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class,args);
}
}
高可用集群配置
- 每个节点配置其他节点地址,形成相互注册
yaml
# 节点1配置
eureka:
client:
service-url:
defaultZone: http://node2:8762/eureka
- 客服端集群配置
yaml
eureka:
client:
service-url:
defaultZone: http://node1:8761/eureka,http://node2:8762/eureka
- 服务端解释
yaml
server:
port: 8761 #eureka默认端口 6379 8080 3306 8848
spring:
application:
name: eureka-server #应用名称,禁用特殊字符
eureka: #eureka配置分为三大类 server client 实例 eureka-server既是服务端也是客户端
server:
eviction-interval-timer-in-ms: 10000 #服务器间隔多少毫秒做定期删除操作
renewal-percent-threshold: 0.85 # 续约百分比 超过85%应用没续约那么eureka会保护服务 不会剔除任何一个服务
instance: # 实例的配置
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} #主机名称:应用名称:端口号
hostname: localhost #主机名称或者服务的ip
prefer-ip-address: true # 以ip形式显示具体服务信息
lease-renewal-interval-in-seconds: 5 #服务实例续约时间的间隔
- 客户端解释
yaml
server:
port: 8080 #客户端的端口没要求
spring:
application:
name: eureka-client-a
# 注册的含义,就是将自己的一些信息发送过去
eureka:
client: # 客户端配置
service-url: #指定注册的地址
defaultZone: http://localhost:8761/eureka
register-with-eureka: true # 可以不往eureka-server注册
fetch-registry: true # 应用是否去拉取服务列表到本地
registry-fetch-interval-seconds: 10 # 为了缓解服务列表脏读问题,时间越短脏读越少(浪费性能)
instance:
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} #主机名称:应用名称:端口号
hostname: localhost #主机名称或者服务的ip
prefer-ip-address: true # 以ip形式显示具体服务信息
lease-renewal-interval-in-seconds: 10 #服务实例续约时间的间隔
- 客户端b配置instance信息
yaml
server:
port: 8081 #客户端的端口没要求
spring:
application:
name: eureka-client-b
# 注册的含义,就是将自己的一些信息发送过去
eureka:
client:
service-url: #指定注册的地址
defaultZone: http://localhost:8761/eureka
instance:
prefer-ip-address: true
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
hostname: localhost
lease-renewal-interval-in-seconds: 10 #续约时间
服务调用
- RestTemplate + 负载均衡
java
@Bean
@LoadBalanced
public RestTemplate restTemplate() { ... }
- feign申明式调用
java
@FeignClient(name = "user-service")
public interface UserServiceClient { ... }
监控与调优
- 心跳与提出时间
yaml
eureka:
instance:
lease-renewal-interval-in-seconds: 30 # 心跳间隔
lease-expiration-duration-in-seconds: 90 # 剔除超时时间
- 关闭自我保护模式
yaml
eureka:
server:
enable-self-preservation: false # 开发环境建议关闭
- 在
application.yml
中配置健康检查
yaml
eureka:
client:
healthcheck:
enabled: true
- 可以通过实现
HealthIndicator
接口来自定义健康检查逻辑
java
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class CustomHealthIndicator implements HealthIndicator {
@Override
public Health health() {
// 自定义健康检查逻辑
if (checkDatabaseConnection()) {
return Health.up().build();
} else {
return Health.down().withDetail("Error", "Database connection failed").build();
}
}
private boolean checkDatabaseConnection() {
// 检查数据库连接
return true;
}
}
- 监控Eureka Server:可以通过Spring Boot Actuator来监控Eureka Server的健康状态和性能指标。首先,在
pom.xml
中添加Actuator依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 然后,在
application.yml
中配置Actuator
yaml
management:
endpoints:
web:
exposure:
include: "*"
- 访问
http://localhost:8761/actuator
,你将看到Eureka Server的各种监控端点 - 日志管理
Eureka Server和Client的日志可以帮助我们排查问题。可以通过以下配置来调整日志级别
java
logging:
level:
com.netflix.eureka: DEBUG
com.netflix.discovery: DEBUG
服务发现与调用
- 创建springboot项目,并且添加以下依赖
Spring Web
Eureka Discovery Client
OpenFeign(用于声明式REST客户端)
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父 POM:Spring Boot 基础依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version> <!-- 推荐稳定版本 -->
<relativePath/> <!-- 从本地仓库查找 -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo-service</artifactId>
<version>1.0.0</version>
<name>demo-service</name>
<description>Demo Service with Eureka and OpenFeign</description>
<properties>
<java.version>17</java.version> <!-- 匹配 Spring Boot 3.x 要求 -->
<spring-cloud.version>2023.0.0</spring-cloud.version> <!-- 对应 Spring Boot 3.2.x -->
</properties>
<!-- 依赖管理:统一 Spring Cloud 组件版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 1. Spring Web:提供 RESTful API 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 2. Eureka Discovery Client:服务注册与发现 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 3. OpenFeign:声明式 REST 客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 可选:测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot 构建插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 在
application.yml
或application.properties
中配置Eureka Client
yaml
spring:
application:
name: service-consumer
server:
port: 8082
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
-
启用Eureka Client和Feign
在Spring Boot应用的启动类上添加
@EnableEurekaClient
和@EnableFeignClients
注解javaimport org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableEurekaClient @EnableFeignClients public class ServiceConsumerApplication { public static void main(String[] args) { SpringApplication.run(ServiceConsumerApplication.class, args); } }
-
创建feign客户端
创建一个Feign客户端接口,用于调用服务提供者的API
java
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "service-provider")
public interface ServiceProviderClient {
@GetMapping("/hello")
String sayHello();
}
- 创建控制器
创建一个控制器,调用Feign客户端并返回结果
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ConsumerController {
@Autowired
private ServiceProviderClient serviceProviderClient;
@GetMapping("/consume")
public String consume() {
return serviceProviderClient.sayHello();
}
}
- 启动服务消费者
运行项目,服务消费者将通过Eureka Server发现服务提供者,并调用其API。访问http://localhost:8082/consume
,你将看到服务提供者返回的结果
- 如果不会创建springboot项目并且集成Eureka可以参考网址:https://blog.csdn.net/m_xiaozhilei/article/details/128654378(从项目创建到后面的Eureka运行成功)
Consul
核心概念
Consul 是一个用于服务发现和配置的分布式系统工具。它提供了服务注册、健康检查、键值存储和分布式锁等功能,使得在分布式系统中管理服务变得更加简单。Consul 的核心功能包括下面几点
- 服务发现:Consul 可以让服务注册自己,并且其他服务可以通过 Consul 找到它们。
- 健康检查:Consul 客户端可以提供健康检查,这些检查结果决定了服务的可用性。
- 键值存储:Consul 提供了一个简单的键值存储,可以用来存储配置信息。
- 分布式锁:Consul 支持分布式锁,这对于同步对共享资源的访问非常有用。
特点:Consul 的设计目标是易于使用、可扩展,并且具有高可用性,它支持多种编程语言的客户端库,并且可以与各种不同的基础设施工具集成
Consul准备环境
环境要求
- 操作系统:64 位操作系统,如 Ubuntu 16.04+、CentOS 7 + 等
- CPU 架构:x86_64 或 ARM
- 内存:至少 512MB RAM,推荐 1GB 或更多,具体取决于预期的工作负载
- 硬盘空间:至少 200MB 的可用硬盘空间
网络配置
- 防火墙:在防火墙上开放Consul 使用的端口(默认为 8300、8301、8302、8500 等)
- DNS:确保服务器可以解析 Consul 集群中的节点名称或 IP 地址
- 时间同步:建议配置 NTP 服务以确保集群中的所有节点时间同步
依赖安装
Consul 不需要特殊的依赖,但是建议安装以下工具来帮助安装和管理 Consul
-
wget/curl:用于下载 Consul 的二进制文件。
-
tar:用于解压下载的 Consul 包。
-
systemd(可选):如果使用 systemd 来管理 Consul 服务,需要确保它已经安装
注意:在确保以上环境准备就绪后,可以开始 Consul 的安装和配置过程
Consul 安装
Consul 的安装可以通过多种方式进行,包括包管理器、源代码编译以及直接下载预编译的二进制文件。下面介绍使用包管理器和直接下载二进制文件两种常见方法
- 使用包管理器安装:对于使用 Ubuntu 或 Debian 系统的用户,可以通过以下命令添加 Consul 的官方仓库并安装 Consul
cmd
wget -q https://apt.repos.intel.com/intel-gpg-pub.key | sudo apt-key add -
echo "deb [arch=amd64] https://apt.repos.intel.com/consul stable main" | sudo tee /etc/apt/sources.list.d/consul.list
sudo apt-get update
sudo apt-get install consul
- 对于 CentOS 或 RHEL 系统的用户,可以使用以下命令
cmd
sudo rpm --import https://packagecloud.io/consul/consul/gpgkey
echo -e "[consul]\nname=Consul\nbaseurl=https://packagecloud.io/consul/consul/el/7/\nenabled=1\ngpgcheck=1\nrepo_gpgcheck=1\ngpgkey=https://packagecloud.io/consul/consul/gpgkey" | sudo tee /etc/yum.repos.d/consul.repo
sudo yum install consul
- 下载二进制文件:如果直接下载预编译的二进制文件,可以访问 Consul 的官方网站或 GitHub 发布页面获取最新版本的二进制文件,以下是一个示例命令
cmd
VERSION="1.11.0"
wget https://releases.hashicorp.com/consul/${VERSION}/consul_${VERSION}_linux_amd64.zip
unzip consul_${VERSION}_linux_amd64.zip
sudo mv consul /usr/local/bin/
注意:确保替换 VERSION
变量为 Consul 的最新版本号
重点:在安装 Consul 之后,可以通过运行 consul --version
来验证安装是否成功。如果返回了 Consul 的版本信息,则表示 Consul 已经成功安装
Consul 配置
配置文件结构
- agent:配置 Consul agent 的行为。
- server:配置 Consul server 节点的特定设置。
- client:配置 Consul client 节点的特定设置。
- cluster:配置集群层面的设置,如数据中心的名称。
- acl:访问控制列表的配置,用于权限管理。
- encrypt:配置集群加密
注意:Consul 的配置文件通常是一个名为 consul.json
的 JSON 文件,也可以是 HCL(HashiCorp Configuration Language)格式的.hcl
文件
创建配置文件
- 创建一个新的配置文件,例如
consul.hcl
,并添加以下基本配置 - 这个配置定义了一个集群名称,并启用了 server 和 client 模式,同时开启了访问控制列表
json
# 全局配置
datacenter = "dc1" # 数据中心名称(默认 dc1)
cluster_name = "example-cluster" # 集群名称(自定义)
data_dir = "/opt/consul" # 数据存储目录(日志、状态等)
# 服务器节点配置(启用服务器模式)
server {
enabled = true # 启用服务器模式(必须为 true 才能作为服务器节点)
bootstrap_expect = 3 # 期望的服务器节点数量(自动引导集群时使用)
}
# 客户端节点配置(启用客户端模式)
client {
enabled = true # 启用客户端模式(允许客户端连接)
bind_addr = "0.0.0.0" # 客户端监听的 IP 地址(0.0.0.0 表示所有网卡)
}
# ACL(访问控制)配置
acl {
enabled = true # 启用 ACL(默认 false,需显式开启)
default_policy = "deny" # 默认策略:拒绝未授权的请求(可选 "allow")
enable_token_persistence = true # 启用 ACL Token 持久化(存储到 data_dir)
}
环境变量
- 除了配置文件,Consul 还支持使用环境变量来覆盖配置文件中的设置。环境变量的命名规则是将配置文件的键转换为大写,并使用下划线分隔。例如,
cluster_name
配置可以通过CONSUL_CLUSTER_NAME
环境变量来设置
json
export CONSUL_CLUSTER_NAME="example-cluster"
配置Consul 服务
- 示例的 systemd 服务文件
consul.service
,在这个服务文件中,-config-dir
参数指定了 Consul 的配置文件所在的目录
ison
[Unit]
Description=Consul
Documentation=https://www.consul.io/docs/
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/local/bin/consul agent -config-dir /etc/consul.d
ExecReload=/bin/kill -HUP $MAINPID
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
知识点:如果使用 systemd 来管理 Consul 服务,可以创建一个 systemd 服务文件来指定 Consul 的配置文件路径和其他启动参数
- 完成配置文件的创建和 systemd 服务文件的设置后,可以通过启动 Consul 服务来应用这些配置
json
sudo systemctl start consul
sudo systemctl enable consul
注意:使用 systemctl status consul
可以检查 Consul 服务的状态,确保它正在运行,配置 Consul 是确保服务按预期运行的关键步骤,正确的配置可以最大化 Consul 的功能并保障集群的安全和稳定性*
启动 Consul 服务
命令行启动
- 如果只是进行测试或者临时启动 Consul,可以使用命令行直接启动 Consul agent。以下是一个基本的启动命令
json
consul agent -dev
注意:这条命令会启动一个开发模式的 Consul agent,它适用于单节点开发和测试。对于生产环境,你需要指定配置文件和相应的参数
- 如果要使用配置文件启动 Consul,可以使用以下命令,确保替换
/path/to/consul.hcl
为你的 Consul 配置文件的实际路径
json
consul agent -config-file /path/to/consul.hcl
使用 systemd 启动
- 在生产环境中,推荐使用 systemd 来管理 Consul 服务,这样可以确保服务在系统重启后自动启动,并且可以方便地进行服务管理
- 首先,确保已经创建了 Consul 的 systemd 服务文件,如上一节中提到的
consul.service
。然后,可以使用以下命令启动 Consul 服务
json
sudo systemctl start consul
- 要使 Consul 服务在系统启动时自动启动,可以使用以下命令
json
sudo systemctl enable consul
- 启动服务后,可以使用以下命令检查 Consul 服务的状态
json
sudo systemctl status consul
- 如果 Consul 服务正在运行,你将看到服务的状态信息。此外,你也可以通过 Consul 的 HTTP API 或者 CLI 命令来检查集群的状态和成员信息
json
consul members
- 这将列出集群中所有节点的状态信息,包括节点的角色(server 或 client)、地址和健康状态
- 启动 Consul 服务是部署过程中的关键步骤,确保 Consul 服务正常运行是后续进行服务注册和发现的基础
Linux/macOS(终端命令)
bash
# 启动 Consul 代理(加载 /etc/consul.d/ 目录下的所有配置)
consul agent -dev -config-dir=/etc/consul.d/
# 或显式指定配置文件(适用于非默认路径)
consul agent -dev -config-file=/path/to/your/config.hcl
Windows(CMD/PowerShell)
cmd
# 命令提示符(CMD)
"C:\consul\consul.exe" agent -dev -config-dir="C:\consul\conf\"
# PowerShell
& "C:\consul\consul.exe" agent -dev -config-dir="C:\consul\conf\"
Consul 集群搭建
Consul 集群的搭建是确保服务发现和服务配置在分布式系统中可靠运行的关键。一个 Consul 集群由一个或多个 Consul 服务器组成,它们之间通过相互通信来维护集群的状态。以下是搭建 Consul 集群的详细步骤
规划集群拓扑
- 在搭建集群之前,需要规划集群的拓扑结构
- Server 节点:负责维护集群的状态,包括服务注册信息、键值对存储和集群配置,Server 节点之间通过 Raft 协议进行通信来保证数据的一致性
- Client 节点:不参与 Raft 协议的共识过程,但可以向 Server 节点注册服务和查询服务信息
- 通常,一个 Consul 集群至少需要 3 个 Server 节点来保证高可用性
配置 Server 节点
- 在每个 Server 节点上,需要配置 Consul 以 server 模式运行。这可以通过编辑 Consul 的配置文件或使用命令行参数来完成
json
{
"server": true,
"bootstrap_expect": 3,
"data_dir": "/var/lib/consul",
"log_level": "INFO"
}
注意:在这个配置中,"server": true
表示该节点是一个 Server 节点,"bootstrap_expect": 3
告诉 Consul 我们期望有 3 个 Server 节点加入集群,这是为了确保集群的稳定性
配置 Client 节点
- Client 节点的配置相对简单,只需要指定它们连接到 Server 节点的地址
json
{
"client": true,
"server": false,
"retry_join": ["<server1_ip>:8300", "<server2_ip>:8300", "<server3_ip>:8300"]
}
注意:在这个配置中,"client": true
表示该节点是一个 Client 节点,"retry_join"
是一个包含 Server 节点地址的列表,Client 节点将尝试连接到这些地址以加入集群
启动 Consul 节点
- 在所有节点上配置好 Consul 后,可以启动 Consul 服务。对于 Server 节点,可以使用以下命令
bash
consul agent -server -bootstrap-expect 3 -config-dir /etc/consul.d
- 对于 Client 节点,可以使用以下命令
bash
consul agent -client -retry-join <server1_ip>:8300 -retry-join <server2_ip>:8300 -retry-join <server3_ip>:8300 -config-dir /etc/consul.d
- 确保替换
<server1_ip>
,<server2_ip>
,<server3_ip>
为实际的 Server 节点 IP 地址。
验证集群状态
- 在所有节点启动后,可以通过 Consul 的 HTTP API 或 CLI 命令来验证集群的状态
bash
consul members
consul info
注意:consul members
命令将列出集群中所有节点的信息,而 consul info
命令将提供关于集群的详细信息,包括集群的 Server 节点数量和 Client 节点数量。
创建 config.hcl
步骤
若默认目录下无 config.hcl
,需手动创建,以下是Linux/macOS的示例步骤(Windows 类似,需调整路径):
- 创建配置目录(若不存在):bash (linux系统)
bash
sudo mkdir -p /etc/consul.d/
- 创建
config.hcl
文件:
bash
bash
sudo touch /etc/consul.d/consul.hcl
- 编辑配置文件(添加必要参数,如数据中心、节点模式等):
bash
bash
sudo nano /etc/consul.d/consul.hcl
- 示例配置(集群模式):hcl
hcl
datacenter = "dc1" # 数据中心名称
data_dir = "/opt/consul" # 数据存储目录
server = true # 启用服务器模式(集群需至少 3 个服务器节点)
bootstrap_expect = 3 # 期望的服务器节点数量
client_addr = "0.0.0.0" # 客户端可访问的 IP 地址
bind_addr = "0.0.0.0" # 绑定的 IP 地址
ui = true # 启用 Web UI
Nacos
下载安装
Windows安装
-
下载地址: https:///alibaba/nacos/releases/tag/2.2.3
-
下载之后进行解压,bin 目录下面是启动和关闭脚本,使用记事本打开 startup.cmd,大概在 26 行左右,把 set MODE="cluster" 改为 set MODE="standalone"
-
由于 Nacos 默认的启动方式是集群,所以启动前需要修改配置为单机模式
-
保存之后再双击打开 startup.cmd,运行成功之后可以看出 Nacos 的端口号为 8848
-
在浏览器中输入 http://127.0.0.1:8848/nacos 就能访问了
-
在 windows 系统下,如果端口号冲突,可以关闭当前占用 8848 端口号下的进程,也可以修改 conf 目录下的 application.properties 文件中的端口号配置
Linux安装
- 在 Linux 系统中也是同样的操作,把刚刚下载的安装包解压之后也是相同的目录

- 此时就需要启动 startup.sh 了,以 Ubuntu 系统为例,同样是以单机模式启动,启动 Nacos 服务的命令为
bash
bash startup.sh -m standalone
-
端口号冲突同样也是两种解决方案
-
在访问之前还需要确保开放云服务器的端口号,除了 8848 端口号,还需要开启 9848 端口号
Nacos的用法
配置导入
- 在父项目中的 dependencyManagement 下导入下面的依赖,版本可以统一管理
xml
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<java.version>17</java.version>
<mybatis.version>3.0.3</mybatis.version>
<mysql.version>8.0.33</mysql.version>
<spring-cloud.version>2022.0.3</spring-cloud.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud-alibaba.version>2022.0.0.0-Rc2</spring-cloud-alibaba.version>
</properties>
-
spring-cloud-alibaba 的版本和 spring boot 也是对应的,具体可见官方文档:https://sca.aliyun.com/docs/2022/overview/version-explain/
xml<properties> <spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.version> </properties> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency>
-
需要引入 nacos 的依赖,order-service 在这里作为客户端需要引入发现服务的依赖
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
- 负载均衡的依赖添加
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
- 在官方文档(https://sca.aliyun.com/docs/2023/user-guide/nacos/quick-start/?spm=5176.29160081.0.0.74805c72Ts51X1)中也给出 Nacos Config 地址的配置格式

yaml
spring:
cloud:
nacos:
discovery:
serverAddr: 127.0.0.1:8848
- 应用名称也需要配置一下
yaml
spring:
application:
name: order-service
- product-service 也做相同的配置
- 按照和 Eureka 一样的方式进行远程调用
java
public OrderInfo selectOrderById(Integer orderId){
OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
String url = "http://product-service/product/" + orderInfo.getProductId();
ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
orderInfo.setProductInfo(productInfo);
return orderInfo;
}
服务下线
- 如果某个服务出现了问题,为了减少损失,需要把这个服务下线,解决好了之后再进行上线

- 例如,把端口号为 9091 的服务下线之后,该服务就不会收到请求了

- 同样的,再点击上线就又可以接收请求了
负载均衡
-
点击编辑就可以修改该服务的权重
-
修改之后再次请求发现,目前 9090 端口和其它端口接收到的请求还是一样的

- 因为 Spring Cloud LoadBalance 组件自身有负载均衡配置的方式,所以不支持 Nacos 的权重属性配置,需要开启 Nacos 的负载均衡策略,让权重生效
yaml
#开启nacos负载均衡策略
spring:
cloud:
loadbalancer:
nacos:
enabled: true
- 此时 order-service 作为客户端发起请求,所以需要配置在 order-service 下,之后重启服务,再重新发起请求,发现此时的权重配置已经生效了
- 在修改权重的时候可能会出现下面的报错

理由:是因为 Nacos 采用 raft 算法来计算 Leader,并且会记录前一次启动的集群地址,当服务器 IP 改变时会导致 raft 记录的集群地址失效,导致选 Leader 出现问题(网络环境发生变化时,IP 地址也会发生变化)
解决办法:解决办法就是删除 Nacos 根目录下 data 文件夹下的 protocol 文件夹
配置同集群优先访问
- 微服务访问时,应该同一个集群优先访问的,例如同一个机房的电脑是在同一个局域网下的,访问速度会快一点

- 配置格式如下
yaml
spring:
cloud:
nacos:
discovery:
server-addr:
cluster-name: BJ #集群名称: 上海集群
- 把 order-service 和 端口号为 9090 的 product-service 的集群都设置为北京

-
9091 和 9092 服务集群的配置方式
-
之后再重启服务,集群就配置成功了

- 此时再发起请求,由于 order-service 的集群为 BJ,那么会优先访问集群为 BJ 的 product-service 了

- 如果把 9090 的服务下线,那么就会访问 SH 的集群了
健康检查:Nacos 提供了两种健康检查机制,一种是客户端主动上报,另一种是服务端反向探测
- 客户端主动上报:客户端会以心跳上报的形式向 Nacos 告知自身健康状态。若 Nacos 在一定时间内未收到客户端的心跳报告,便会将该实例置为不健康状态。若继续在超过另一段更长的时间后仍未收到报告,就会将实例从注册列表中删除,以此来确保注册列表中的实例都是活跃可用的。
- 服务端反向探测:Nacos 服务器主动对客户端进行健康状态探测,若探测失败,实例会被标记为不健康。这样在进行服务调用时,负载均衡器等组件就不会将请求分发到这些不健康的实例上,以保障服务质量,但一般不会立即删除该实例,以便在实例恢复健康后可继续使用

- Nacos 的服务实例(注册的节点)又分为临时实例和非临时实例
- 临时实例:如果实例宕机超过一定时间,会从服务列表去除
- 非临时实例:如果实例宕机,不会从服务列表去除
- Nacos 对临时实例采取的是客户端主动上报的机制,对于非临时实例,采取服务器端反向探测机制,之前创建的服务都是非临时的,可以通过下面的配置来设置非临时实例
yaml
spring:
cloud:
nacos:
discovery:
ephemeral: false # 设置为⾮临时实例
- 把 order-service 设置为非临时实例之后,Nacos 检测到 order-service 状态异常,就会把它的健康状态设置为 false

- 在设置实例类型的时候可能会出现报错

原因:这是因为 Nacos 会记录每一个服务实例的 IP 和端口号,当发现 IP 和端口号都没有发生变化时,Nacos 不允许一个服务实例类型发生变化
解决办法:就是先停止 Nacos 的服务,然后删除 Nacos 目录下 /data/protocol/raft 中的信息,再重启服务
环境隔离
- Nacos 提供了 namespace(命名空间)来实现环境的隔离,不同的命名空间的服务不可见,通过以下方式在 Nacos 上创建命名空间

yaml
spring:
cloud:
nacos:
discovery:
namespace: 51152a13-7911-49e3-bbdc-16fd5670a257
- 通过命名空间 ID 来配置属于哪个环境:此时只有 order-service 在 dev 环境下,所以再去访问 product-service 是会报错的,处于同一个环境下才能访问到

nacos配置
除了注册中心之外,Nacos 还是一个配置中心,具备配置管理的功能,当前项目的配置都在代码中,就会存在一些问题
- 配置文件修改时,服务需要重新部署,在微服务架构中,一个服务有很多个实例,一个一个的部署比较麻烦,并且也容易出错
- 多人开发时,配置文件可能需要经常修改,使用同一个配置文件容易出现冲突
- 配置中心就是对这些配置项进行统一管理,通过配置中心,可以集中查看,修改和删除配置,不用再逐个修改配置文件了
- 先分别创建 public 和 dev 环境下的配置

- 在 product-service 导入依赖
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>
- 微服务启动前需要获取 Nacos 中的配置,并与 application.tml 配置合并,需要使用 bootstrap.properties 或者 bootstrap.yml 配置文件来配置 Nacos Server 地址
yaml
spring:
application:
name: product-service
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
- 接下来尝试获取 Nacos 中的配置内容
java
@RestController
public class NacosController {
@Value("${nacos.config}")
private String nacosConfig;
@RequestMapping("/getConfig")
public String getConfig() {
return "从nacos获取配置项nacos.config: " + nacosConfig;
}
}
- ${nacos.config} 要和配置中的配置项保持一致

- 此时如果修改 Nacos 配置中心的配置,再次获取还是修改前的,如果要实现实时更新还需要加上 @RefreshScope注解

- Nacos 配置中心的命名空间和注册中心的命名空间是分别设置的,默认都是 public,所以 bootstrap.yml 中也需要配置一下命名空间

- 配置之后再访问就是对应配置好的命名空间的配置

- 关于 Data ID 的介绍

- 在开始之前配置的是 product-service,完整的格式应该是

-
刚开始添加配置时就选择的配置文件类型为 properties,所以这里可以不用再配置了,接下来把 active 配置为 dev
-
在日志中可以看出是监听了三个类型的文件配置,如果这三个类型配置都配置上的话它们的一个优先级如下


部署到云服务器
- 这次部署和之前有些不一样,由于 product-service 中多了一个 bootstrap.yml 配置文件,其中已经配置好了 profiles.active,所以可以直接改成 @profile.name@,然后只需要分别配置 dev 和 prod 下的配置
- 除此之外还需要加上以下配置,使用过滤功能将环境相关的信息注入到配置文件中

Nacos 和 Eureka 的区别
- 共同点:都支持服务注册和服务拉取
区别
-
功能上:Nacos 提供了更丰富的功能,除了服务发现和注册之外,还包括配置管理(配置中心)、流量管理、DNS服务等。这使得Nacos可以作为微服务架构中的一个更全面的解决方案。Eureka 主要专注于服务发现和注册,没有Nacos那么丰富的功能
-
CAP 理论:Eureka 遵循 AP(可用性-分区容错性)原则,Nacos 可以灵活地在 AP 和 CP(一致性-分区容错性)模式之间切换,默认情况下是 AP 模式,也可以根据需要配置为 CP 模式
-
服务发现:Eureka 采用基于拉(Pull)模式的服务发现机制。Eureka客户端(Eureka Client)会定期从Eureka服务器(Eureka Server)拉取服务信息,并且会缓存这些信息,默认每30秒更新一次。Nacos 采用基于推(Push)模式的服务发现机制。当服务列表发生变化时,Nacos服务器会实时推送这些变化给所有订阅了该服务的客户端,同时服务端和客户端之间会保持心跳连接,以确保服务信息的实时性和准确性
开始之前配置的是 product-service,完整的格式应该是
外链图片转存中...(img-qeReD3Lg-1752119448596)
- 刚开始添加配置时就选择的配置文件类型为 properties,所以这里可以不用再配置了,接下来把 active 配置为 dev
外链图片转存中...(img-nodyIQOn-1752119448596)
- 在日志中可以看出是监听了三个类型的文件配置,如果这三个类型配置都配置上的话它们的一个优先级如下
外链图片转存中...(img-UiChbrLz-1752119448596)
外链图片转存中...(img-yLBwomMW-1752119448596)
部署到云服务器
- 这次部署和之前有些不一样,由于 product-service 中多了一个 bootstrap.yml 配置文件,其中已经配置好了 profiles.active,所以可以直接改成 @profile.name@,然后只需要分别配置 dev 和 prod 下的配置
外链图片转存中...(img-zdk5pSZ6-1752119448597)
外链图片转存中...(img-vVhA0uqp-1752119448597)
- 除此之外还需要加上以下配置,使用过滤功能将环境相关的信息注入到配置文件中
外链图片转存中...(img-oDqBMtlG-1752119448597)
Nacos 和 Eureka 的区别
- 共同点:都支持服务注册和服务拉取
区别
-
功能上:Nacos 提供了更丰富的功能,除了服务发现和注册之外,还包括配置管理(配置中心)、流量管理、DNS服务等。这使得Nacos可以作为微服务架构中的一个更全面的解决方案。Eureka 主要专注于服务发现和注册,没有Nacos那么丰富的功能
-
CAP 理论:Eureka 遵循 AP(可用性-分区容错性)原则,Nacos 可以灵活地在 AP 和 CP(一致性-分区容错性)模式之间切换,默认情况下是 AP 模式,也可以根据需要配置为 CP 模式
-
服务发现:Eureka 采用基于拉(Pull)模式的服务发现机制。Eureka客户端(Eureka Client)会定期从Eureka服务器(Eureka Server)拉取服务信息,并且会缓存这些信息,默认每30秒更新一次。Nacos 采用基于推(Push)模式的服务发现机制。当服务列表发生变化时,Nacos服务器会实时推送这些变化给所有订阅了该服务的客户端,同时服务端和客户端之间会保持心跳连接,以确保服务信息的实时性和准确性