文章目录
- 1.版本管理以及构建规范
- 2.Nacos快速开始
- 3.项目结构介绍
- 4.注册中心
-
- 3.1依赖引入
- [3.2 生产者服务注册到Nacos](#3.2 生产者服务注册到Nacos)
- 3.3消费者服务注册到Nacos
- 3.4启动服务运行效果
- 5.建立消费者微服务集群
- 6.IDEA中services控制台开启
- 7.注册中心-服务发现
- 8.远程调用
- 9.负载均衡
-
- [9.1 依赖导入](#9.1 依赖导入)
- [9.2 LoadBalancerClient](#9.2 LoadBalancerClient)
- [9.3 @LoadBalanced注解](#9.3 @LoadBalanced注解)
- 9.4.面试题
- 10.配置中心
-
- [10.1 依赖导入](#10.1 依赖导入)
- [10.2 配置文件](#10.2 配置文件)
- [10.3 Nacos平台配置](#10.3 Nacos平台配置)
- [10.4 验证配置是否生效](#10.4 验证配置是否生效)
- [10.5 导入多个 Nacos 配置集(多环境 / 多业务配置)](#10.5 导入多个 Nacos 配置集(多环境 / 多业务配置))
- 11.注册中心和配置中心总结
1.版本管理以及构建规范
1.1版本管理
参考SpringClooud Alibaba:https://github.com/alibaba/spring-cloud-alibaba/blob/2023.x/README-zh.md

1.2如何构建

1.3本文案例演示版本
shell
JDK:17
Nacos:2.4.3
SpringBoot:3.3.4
SpringCloud:2023.0.3
SpringCloud Alibaba:2023.0.3.2
2.Nacos快速开始
Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的⾸字⺟简称,⼀个更易于构
建云原⽣应⽤的动态服务发现、配置管理和服务管理平台。
2.1安装
Nacos快速开始地址:https://nacos.io/docs/next/quickstart/quick-start/
根据官网地址即可完成对于Nacos的安装
2.2启动

3.项目结构介绍
本文的样式项目是一个基于Maven的多模块项目,下图为本示例项目的项目结构:
2个服务:生产者服务和消费者服务

4.注册中心
3.1依赖引入
pom.xml文件
xml
<!-- 注册中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
3.2 生产者服务注册到Nacos
3.2.1 编写配置文件
application.yml
yaml
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848 # Nacos地址
application:
name: service-product # 服务名称
server:
port: 9002 # web端口
3.2.2 开启Nacos发现注解
一般都是添加到启动类上
java
package cn.varin.service.product;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class ServiceProductApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceProductApplication.class, args);
}
}
3.3消费者服务注册到Nacos
3.3.1 编写配置文件
application.yml
yaml
spring:
application:
name: service-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
server:
port: 9001
3.3.2 开启Nacos发现注解
一般都是添加到启动类上
java
package cn.varin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class ServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumerApplication.class, args);
}
}
3.4启动服务运行效果

5.建立消费者微服务集群
建立方式:采用同一套方法使用不同的启动端口配置,具体配置参考如下
- 点击Edit Configurations

- 选择Consumer服务并且点击复制按钮

- 复制完成后,点击复制服务的modify options选项并且勾选**add JVM options**

- 此时页面会多出来一个jvm option 输入框
填写内容:-DServer.port = 端口

- 多重复几次,并且将复制的服务一起启动,即可在Nacos注册中心看到多个实例


6.IDEA中services控制台开启
注意:有时候idea编辑器会自动提示是否开启Services面板管理微服务模块,就无需配置。
如果并没有的话,可以根据以下配置完成对于Services面板的开启
- 找到.idea目录中的workSpace.xml文件,并在文件中添加以下内容
注意:给配置需要添加在 标签中。
xml
<component name="RunDashboard">
<option name="configurationTypes">
<set>
<option value="SpringBootApplicationConfigurationType" />
</set>
</option>
</component>
- 再重新启动各个服务就可以看到services面板了

7.注册中心-服务发现
SpringCloud 和SpringCloud Alibaba 都提供了服务发现的功能
7.1DisconveryClient
java
package cn.varin.service.consumer.test;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.discovery.DiscoveryClient;
@SpringBootTest
@Slf4j
public class DiscoveryClientTest {
@Resource
private DiscoveryClient discoveryClient;
@Test
public void discover() {
discoveryClient.getServices().forEach(serviceName -> {
System.err.println(serviceName);
log.info("discover serviceName={}", serviceName);
discoveryClient.getInstances(serviceName).forEach(serviceInstance -> {
log.info(serviceName+">>>"+serviceInstance.getHost()+":"+serviceInstance.getPort());
});
});
}
}
运行代码后可以发现Nacos中的两个服务

7.2NacosDiscoveryClient和NacosServiceDiscovery
这两个类都可以获取到注册中心的服务
| 对比维度 | NacosDiscoveryClient | NacosServiceDiscovery |
|---|---|---|
| 核心定位 | Spring Cloud 标准服务发现客户端(API层) | Nacos 专属的服务发现底层实现(服务层) |
| 实现接口 | 实现 Spring Cloud 的 DiscoveryClient 接口 |
无统一接口,是 Nacos 自定义的服务发现实现类 |
| 设计目的 | 遵循 Spring Cloud 规范,给开发者提供统一API | 封装 Nacos Server 交互逻辑,给上层API提供支撑 |
| 使用场景 | 开发者日常开发(获取服务实例、自身服务信息) | 框架内部依赖、高级定制(如自定义订阅、多命名空间精细控制) |
| 依赖关系 | 依赖 NacosServiceDiscovery 实现核心功能 |
依赖 Nacos 原生 SDK(nacos-client) |
| API风格 | Spring Cloud 标准化方法(简洁、通用) | Nacos 专属方法(细粒度、强针对性) |
| 是否暴露给开发者 | 是(官方推荐直接使用) | 否(默认内部使用,可手动注入定制) |
java
package cn.varin.service.consumer.test;
import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClient;
import com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;
import com.alibaba.nacos.api.exception.NacosException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import java.util.List;
@SpringBootTest
@Slf4j
public class NacosDiscoveryClientTest {
@Resource
private NacosDiscoveryClient nacosDiscoveryClient;
@Test
public void NacosDiscoveryClientTest() {
// 获取注册中心所有的服务
List<String> services = nacosDiscoveryClient.getServices();
services.forEach(System.out::println);
log.info("======================================");
// 根据服务名称获取到注册中心的集群服务
List<ServiceInstance> instances = nacosDiscoveryClient.getInstances("service-consumer");
instances.forEach(System.out::println);
}
@Resource
private NacosServiceDiscovery nacosServiceDiscovery;
@Test
public void NacosServiceDiscoveryTest() {
try {
nacosServiceDiscovery.getServices().forEach(servierName->{
try {
nacosServiceDiscovery.getInstances(servierName).forEach(
instance->{
log.info(servierName+">>>"+instance.getHost()+":"+instance.getPort());
}
);
} catch (NacosException e) {
throw new RuntimeException(e);
}
});
} catch (NacosException e) {
throw new RuntimeException(e);
}
}
}
运行结果:

8.远程调用
使用RestTemplate类
可调用本项目中的其他模块接口
也可调用第三方服务API
缺点:当远程服务器宕机,则服务不可用
- 测试代码
java
package cn.varin.service.consumer.test;
import com.alibaba.cloud.nacos.discovery.NacosDiscoveryClient;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.client.RestTemplate;
@SpringBootTest
public class RestTemplateTest {
@Resource
private RestTemplate restTemplate;
@Test
public void test() {
RestTemplate template = new RestTemplate();
// 第三方接口调用
String baiduApi = template.getForObject("http://www.baidu.com", String.class);
System.out.println(baiduApi);
// 调用product模块接口
String productAPi = template.getForObject("http://localhost:9101/health", String.class);
System.out.println(productAPi);
}
}
- 测试结果

9.负载均衡
解决问题:可解决微服务模块某一台服务宕机后,若存在集群则可自动切换。
9.1 依赖导入
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
9.2 LoadBalancerClient
使用LoadBalancerClient类实现接口发现负载均衡
- 测试代码
java
package cn.varin.service.consumer.test;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.client.RestTemplate;
@SpringBootTest
public class LoadBalancerTest {
@Resource
private LoadBalancerClient loadBalancerClient;
@Test
public void LoadBalancerClientTest() {
ServiceInstance choose = loadBalancerClient.choose("service-product");
if (choose == null) {
throw new RuntimeException("未找到 service-product 实例");
}
// String uri= "http://127.0.0.1:"+choose.getPort()+"/health";
String uri= "http://"+choose.getHost()+":"+choose.getPort()+"/health";
System.out.println(uri);
RestTemplate template = new RestTemplate();
String forObject = template.getForObject(uri, String.class);
System.out.println(forObject);
}
}
- 测试结果

9.3 @LoadBalanced注解
- 直接在注册RestTemplate时,给它添加上@LoadBalanced
- uri就可以写成:http://微服务名称/health
具体步骤:
- 添加注解
java
package cn.varin.service.consumer.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class NacosConfig {
@Bean
@LoadBalanced // 实现负载均衡
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(30000);
factory.setReadTimeout(30000);
return new RestTemplate(factory);
}
}
- 测试
java
package cn.varin.service.consumer.test;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.client.RestTemplate;
@SpringBootTest
public class LoadBalancerTest {
@Autowired
private RestTemplate restTemplate;
@Test
public void loadBalancedTest() {
String uri = "http://service-product/health";
String forObject = restTemplate.getForObject(uri, String.class);
System.out.println(forObject);
}
}
- 效果

9.4.面试题
- 面试题:如果注册中心宕机了,远程调用还会成功吗?
- 从未调⽤过,如果宕机,调⽤会⽴即失败
- 调⽤过,如果宕机,因为会缓存名单,调⽤会成功
- 调⽤过,如果注册中⼼和对⽅服务宕机,因为会缓存名单,调⽤会阻塞后失败(Connection
Refused)
核心结论:可能成功,但取决于服务消费者是否已缓存服务提供者的地址,且服务提供者状态正常。
关键原理:Nacos的服务发现与本地缓存机制
Nacos作为注册中心,核心是提供「服务地址注册与查询」能力,而远程调用的核心是「获取服务地址后建立网络连接」,两者独立解耦:
- 服务发现流程 :
- 服务提供者启动时,向Nacos注册自身地址(IP:端口)、元数据等信息;
- 服务消费者启动时,向Nacos查询目标服务的地址列表,并将地址缓存到本地内存(默认无持久化,部分版本支持本地文件缓存);
- 消费者后续调用时,优先从本地缓存获取地址,无需每次查询Nacos。
- 注册中心宕机后的影响边界 :
- 宕机后,新启动的消费者无法查询服务地址,调用直接失败;
- 已启动且缓存了地址的消费者,只要缓存未失效、服务提供者正常运行,就能通过缓存地址完成调用。
补充细节
- 缓存有效期 :Nacos客户端默认会定期(默认30秒)向注册中心刷新服务列表(主动拉取),宕机后刷新失败,缓存不会主动失效,直到:
- 消费者重启(内存缓存丢失);
- 服务提供者下线(但注册中心宕机后,提供者下线状态无法同步给消费者,可能出现"缓存地址已失效"的调用失败)。
- 高可用优化 :
- 生产环境中Nacos需部署集群(至少3节点),避免单点宕机;
- 消费者可开启本地文件缓存(
spring.cloud.nacos.discovery.naming-cache-persist=true),重启后仍能复用缓存地址; - 结合负载均衡组件(如Ribbon、Spring Cloud LoadBalancer),即使部分提供者下线,消费者也能通过缓存中的其他地址重试。
10.配置中心
10.1 依赖导入
xml
<!-- 配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
10.2 配置文件
consumer模块实例
yaml
spring:
application:
name: service-consumer
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
discovery:
server-addr: 127.0.0.1:8848
service: ${spring.application.name}
config:
# 完整写法:data-id + group + namespace + 扩展参数
# import: nacos:${data-id}:${group}:${namespace}?${参数1}&${参数2}
import: nacos:service-consumer
server:
port: 9001
各字段含义

10.3 Nacos平台配置
service-consumer

10.4 验证配置是否生效
在代码中通过 @Value 或
@ConfigurationProperties注入配置,验证是否能获取到 Nacos 中的值本文就展示:ConfigurationProperties
java
package cn.varin.service.consumer.pojo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "consumer")
public class PropertiesData {
private String name;
}
java
package cn.varin.service.consumer.controller;
import cn.varin.service.consumer.pojo.PropertiesData;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/properties")
public class PropertiesController {
@Resource
private PropertiesData propertiesData;
@GetMapping("/getData")
public String getData() {
System.out.println(propertiesData.getName());
System.out.println(propertiesData.toString());
return propertiesData.getName();
}
}

10.5 导入多个 Nacos 配置集(多环境 / 多业务配置)
如果需要导入多个配置文件(如公共配置 + 业务配置),用数组形式指定:
yaml
yaml
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
config:
import:
- nacos:common-prod.yaml:common-group:prod-namespace-id # 公共配置(如数据库、Redis 地址)
- nacos:user-service-prod.yaml:user-group:prod-namespace-id # 业务配置(用户服务专属配置)
11.注册中心和配置中心总结
