SpringCloud 微服务架构与 Nacos
https://github.com/WuSangui571/cloud-demo 中的 README.md 文件浏览,该笔记是记录从 2025 年 9 月 21 日开始的 SpringCloud 学习过程,此处发表的是经由 AI 润色过的精简版。
1. 分布式架构概述
在项目部署中,常见的架构类型包括单体架构、集群架构和分布式架构。以下分别介绍其特点与适用场景。
1.1 单体架构
单体架构将整个应用程序部署在单一服务器上,用户通过域名访问绑定的公网 IP 地址。
优点:
部署简单,适合小型项目或初期开发。
缺点:
高并发场景下,单点故障风险高,容易导致服务不可用。
1.2 集群架构
集群架构通过网关(如 Nginx)将用户请求分发到多个服务器,每个服务器部署相同的应用程序。
优点:
有效应对高并发,降低单点故障风险。
缺点:
无法模块化升级维护,难以支持多语言开发。
1.3 分布式架构
分布式架构将应用程序拆分为多个功能模块,部署在不同服务器上,通过网关分发用户请求。
优点:
支持高并发,模块间独立,可使用多种语言开发,便于维护和升级。
单一模块故障不影响全局服务。
缺点:
系统复杂性增加,需依赖服务注册与配置管理工具(如 Nacos)。
2. 搭建首个 SpringCloud 微服务项目
本节以一个简单的订单与商品微服务项目为例,展示 SpringCloud 的基本搭建流程。
2.1 项目版本选型
为确保兼容性,明确项目使用的框架和组件版本如下:
| 框架/组件 | 版本 |
|---|---|
| SpringBoot | 3.3.4 |
| SpringCloud | 2023.0.3 |
| SpringCloud Alibaba | 2023.0.3.2 |
| Nacos | 2.4.3 |
| Sentinel | 1.8.8 |
| Seata | 2.2.0 |
2.2 创建 SpringBoot 项目
创建一个新的 SpringBoot 项目,命名为
cloud-demo。删除除
.idea和pom.xml外的所有文件。修改
pom.xml,添加 SpringCloud 和 SpringCloud Alibaba 依赖,并配置打包方式为pom:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.4</version>
<relativePath/>
</parent>
<packaging>pom</packaging>
<groupId>com.sangui</groupId>
<artifactId>cloud-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cloud-demo</name>
<description>SpringCloud 微服务演示项目</description>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>2023.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2023.0.3.2</spring-cloud-alibaba.version>
</properties>
<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>
<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>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>2.3 创建服务模块
在
cloud-demo下创建子模块services,设置为pom打包方式,删除其src文件夹。修改
services的pom.xml:
<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>
<parent>
<groupId>com.sangui</groupId>
<artifactId>cloud-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<packaging>pom</packaging>
<artifactId>services</artifactId>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>在
services下创建两个微服务模块:service-product和service-order,均为普通 Java 模块。
2.4 配置公共模型模块
为避免重复定义实体类,在 cloud-demo 下创建 model 模块,存放公共实体类(如 Product 和 Order)。在 service-product 和 service-order 的 pom.xml 中添加 model 依赖:
<dependency>
<groupId>com.sangui</groupId>
<artifactId>model</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>3. Nacos 服务注册与发现
Nacos(Dynamic Naming and Configuration Service)是一个云原生应用的动态服务发现、配置管理和服务管理平台,官方地址:https://nacos.io。
3.1 Nacos 安装与启动
下载:从 https://nacos.io/download/nacos-server/ 下载 Nacos 2.4.3 二进制包。
启动:解压后进入
bin目录,执行以下命令以单机模式启动(Windows 环境):
startup.cmd -m standalone访问:打开浏览器,输入
http://localhost:8848/nacos/,即可访问 Nacos 管理界面,核心功能包括配置管理和服务管理。
3.2 服务注册
添加依赖:
在
cloud-demo的pom.xml中添加 Nacos 服务发现依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>在子模块(如
service-order)中添加 Web 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>配置微服务:
在
service-order的application.yaml中配置服务名称和 Nacos 地址:
spring
application
nameservice-order
cloud
nacos
server-addr127.0.0.18848
server
port8000编写主入口程序:
示例:
service-order的主程序:
package com.sangui.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author sangui
* @createTime 2025-09-21
* @description 订单微服务主入口
* @version 1.0
*/
public class OrderMainApplication {
public static void main(String[] args) {
SpringApplication.run(OrderMainApplication.class, args);
}
}验证注册:
启动
service-order和service-product(端口分别为 8000 和 9000)。访问 Nacos 管理界面,查看服务列表,确认微服务注册成功。
模拟集群:
通过修改端口号(如 8001、9001、9002)启动多个实例,Nacos 服务列表将显示实例数量(如
service-order2 个实例,service-product3 个实例)。
3.3 服务发现
启用服务发现:
在微服务主类上添加
@EnableDiscoveryClient注解。
测试服务发现:
使用
DiscoveryClient或NacosServiceDiscovery查询服务实例:
package com.sangui.product;
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.discovery.DiscoveryClient;
import java.util.List;
/**
* @author sangui
* @createTime 2025-09-22
* @description 服务发现测试
* @version 1.0
*/
public class DiscoveryTest {
private DiscoveryClient discoveryClient;
void discoveryClientTest() {
for (String service : discoveryClient.getServices()) {
System.out.println("服务名称: " + service);
List<ServiceInstance> instances = discoveryClient.getInstances(service);
for (ServiceInstance instance : instances) {
System.out.println("服务: " + service + ",IP: " + instance.getHost() + ",端口: " + instance.getPort());
}
}
}
}3.4 微服务 API 开发
以订单和商品服务交互为例,展示微服务间远程调用。
商品服务:
定义
Product实体类(位于model模块):
package com.sangui.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @author sangui
* @createTime 2025-09-22
* @description 商品实体类
* @version 1.0
*/
public class Product {
private Long id;
private BigDecimal price;
private String productName;
private Integer number;
}实现商品服务接口:
package com.sangui.product.controller;
import com.sangui.model.Product;
import com.sangui.product.service.ProductService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
/**
* @author sangui
* @createTime 2025-09-22
* @description 商品服务控制器
* @version 1.0
*/
public class ProductController {
private ProductService productService;
("/product/{id}")
public Product getProduct(("id") Long productId) {
return productService.getProductById(productId);
}
}订单服务:
定义
Order实体类(位于model模块):
package com.sangui.model;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* @author sangui
* @createTime 2025-09-22
* @description 订单实体类
* @version 1.0
*/
public class Order {
private Long id;
private BigDecimal totalAmount;
private Long userId;
private String nickName;
private String address;
private List<Product> productList;
}实现订单服务接口,包含远程调用商品服务:
package com.sangui.order.service.impl;
import com.sangui.model.Order;
import com.sangui.model.Product;
import com.sangui.order.service.OrderService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal;
import java.util.Arrays;
/**
* @author sangui
* @createTime 2025-09-22
* @description 订单服务实现
* @version 1.0
*/
public class OrderServiceImpl implements OrderService {
private DiscoveryClient discoveryClient;
private RestTemplate restTemplate;
public Order createOrder(Long productId, Long userId) {
Product product = getProductFromRemote(productId);
Order order = new Order();
order.setId(1011L);
order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNumber())));
order.setUserId(userId);
order.setNickName("张三");
order.setAddress("北京");
order.setProductList(Arrays.asList(product));
return order;
}
private Product getProductFromRemote(Long productId) {
List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
ServiceInstance instance = instances.get(0);
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/product/" + productId;
log.info("远程请求 URL: {}", url);
return restTemplate.getForObject(url, Product.class);
}
}测试:
访问
http://localhost:8000/create?productId=1&userId=2,返回订单信息,包含商品数据。
3.5 负载均衡
为实现服务实例的负载均衡,引入 SpringCloud LoadBalancer。
添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>配置 RestTemplate:
在
OrderServiceConfig中添加@LoadBalanced注解:
package com.sangui.order.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author sangui
* @createTime 2025-09-22
* @description 订单服务配置
* @version 1.0
*/
public class OrderServiceConfig {
public RestTemplate restTemplate() {
return new RestTemplate();
}
}优化远程调用:
使用服务名直接调用,无需手动指定实例:
private Product getProductFromRemoteWithLoadBalance(Long productId) {
String url = "http://service-product/product/" + productId;
log.info("远程请求 URL: {}", url);
return restTemplate.getForObject(url, Product.class);
}验证负载均衡:
多次调用订单创建接口,日志显示请求均匀分发到
service-product的不同实例(端口 9000、9001、9002)。
3.6 Nacos 配置中心
Nacos 提供动态配置管理功能,支持配置的集中管理和实时刷新。
添加依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>配置导入:
在
application.yaml中指定导入的 Nacos 配置文件:
spring
config
import
nacos:service-order.yaml创建 Nacos 配置:
在 Nacos 管理界面创建配置文件(如
service-order.yaml),示例内容:
order
timeout30min
auto-confirm7d动态刷新:
使用
@ConfigurationProperties实现配置自动刷新:
package com.sangui.order.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author sangui
* @createTime 2025-09-22
* @description 订单配置类
* @version 1.0
*/
(prefix = "order")
public class OrderProperties {
private String timeout;
private String autoConfirm;
}在控制器中使用:
package com.sangui.order.controller;
import com.sangui.model.Order;
import com.sangui.order.properties.OrderProperties;
import com.sangui.order.service.OrderService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @author sangui
* @createTime 2025-09-22
* @description 订单控制器
* @version 1.0
*/
public class OrderController {
private OrderProperties orderProperties;
private OrderService orderService;
("/create")
public Order createOrder(("productId") Long productId,
("userId") Long userId) {
return orderService.createOrder(productId, userId);
}
("/config")
public String config() {
return "orderTimeout=" + orderProperties.getTimeout() + ",orderAutoConfirm=" + orderProperties.getAutoConfirm();
}
}配置监听:
通过
NacosConfigManager监听配置文件变化:
package com.sangui.order;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import java.util.concurrent.Executors;
/**
* @author sangui
* @createTime 2025-09-21
* @description 订单微服务主入口
* @version 1.0
*/
public class OrderMainApplication {
ApplicationRunner applicationRunner(NacosConfigManager nacosConfigManager) {
return args -> {
ConfigService configService = nacosConfigManager.getConfigService();
configService.addListener("service-order.yaml", "DEFAULT_GROUP", new Listener() {
public java.util.concurrent.Executor getExecutor() {
return Executors.newFixedThreadPool(4);
}
public void receiveConfigInfo(String configInfo) {
System.out.println("配置文件变更: " + configInfo);
System.out.println("邮件通知(模拟)...");
}
});
};
}
public static void main(String[] args) {
SpringApplication.run(OrderMainApplication.class, args);
}
}3.7 配置冲突与优先级
当 Nacos 配置与本地 application.yaml 冲突时,Nacos 配置优先生效。优先级规则:
外部配置(如 Nacos)优先于本地配置。
若导入多个配置文件,先导入的配置优先。
3.8 多环境配置隔离
为支持多环境(如 test、dev、prod),Nacos 使用命名空间(namespace)、分组(group)和数据 ID(Data ID)实现配置隔离。
配置示例:
spring
profiles
activetest
cloud
nacos
config
namespace$spring.profiles.activedev
import-check
enabledfalse
---
spring
config
import
nacos:service-order1.yaml?group=order
nacos:service-order2.yaml?group=order
activate
on-profiletest
---
spring
config
import
nacos:service-order1.yaml?group=order
nacos:service-order2.yaml?group=order
nacos:service-order3.yaml?group=order
activate
on-profiledev说明:
命名空间:区分不同环境(如
test、dev)。分组:区分不同微服务(如
order)。Data ID:区分同一微服务的不同配置文件。
激活配置:通过
spring.profiles.active切换环境。
3.9 Nacos 注册中心高可用性
问题:若 Nacos 注册中心宕机,微服务远程调用是否受影响?
解答:
已调用过注册中心:微服务会缓存实例信息,宕机后仍可通过缓存调用,影响较小,但无法实时更新实例状态。
未调用过注册中心:首次调用无法获取实例信息,远程调用失败。
优化建议:部署 Nacos 集群以提高高可用性,避免单点故障。
- 微信
- 赶快加我聊天吧

- 赶快加我聊天吧
