架构
单体架构

ALL IN ONE 单体架构意味着:
- 单一部署单元:所有功能模块(商品、订单、用户、支付、物流等)都打包在一个Java项目里。
- 共享环境:这些模块运行在同一个JVM进程、同一台服务器上,并通常连接同一个数据库。
优点
| 优点 | 具体说明 |
|---|
| 开发简单 | 单一项目,IDE管理方便,调试容易,无需考虑服务间调用。 |
| 测试容易 | 只需启动一个应用即可进行端到端测试。 |
| 部署单一 | 只需部署一个JAR/WAR包,运维成本低。 |
| 事务管理简单 | 所有模块共享一个数据库,利用本地事务(@Transactional)即可保证ACID。 |
缺点
| 缺点 | 具体表现 |
|---|
| 并发能力受限 | 整个应用只能整体横向扩展(增加多个相同副本),无法针对高并发的商品模块单独扩容。 |
| 可靠性差 | 一个模块(如支付)的内存泄漏或死锁,会导致整个应用崩溃。 |
| 维护成本递增 | 代码量巨大(数百万行),不同模块代码耦合,修改一处可能影响全局,IDE编译变慢。 |
| 技术选型锁死 | 所有模块共用技术栈(如Java版本、框架版本),无法为不同场景选择合适工具。 |
集群架构
把同一个应用部署在多台服务器上,通过负载均衡将用户请求分发到不同的服务器。
| 单体架构的问题 | 集群架构的解决方案 |
|---|
| 单点故障 → 应用崩溃则服务全挂 | 一台服务器宕机,负载均衡将流量切到其他节点 |
| 无法应对高并发 → 单一JVM处理能力有限 | 水平扩展:增加服务器节点即可提升吞吐量 |
| 数据库压力大 → 所有请求读写同一库 | 读写分离:主库写、从库读,分摊压力 |
| 问题 | 说明 |
|---|
| 代码依然耦合 | 所有模块(商品、订单、支付)仍在同一个项目里,修改一个模块需要重新部署整个集群 |
| 数据库仍是瓶颈 | 虽然做了读写分离,但单张表数据量过大时,主库写入压力依然集中 |
| session共享问题 | 用户登录后请求落到不同服务器,需要引入Redis等中间件共享session |
| 分布式事务 | 涉及多个模块的写操作(如下单扣库存),单体本地事务不再适用,需要分布式事务方案 |
分布式微服务架构
分布式
我们按照业务拆分,每个模块又叫微服务,可以独立的开发,测试,部署,升级,扩展。
数据库同样可以根据业务拆分,每个数据库只存储一部分数据。

部署架构
每一个服务器不在部署一个应用,而是部署多个微服务模块。对于访问量大的模块,可以部署多个实例。

核心组件说明
| 组件 | 作用 | 你的笔记对应 |
|---|
| Nacos | 服务注册发现 + 配置中心 | ✅ 注册配置中心 |
| Spring Cloud Gateway | 统一入口、路由、认证、限流 | ✅ 网关 |
| OpenFeign | 服务间声明式HTTP调用 | ✅ 远程调用 |
| Sentinel | 服务熔断、降级、限流 | ✅ 服务熔断 |
| Seata | 分布式事务(AT/TCC/SAGA模式) | ✅ 分布式事务 |
Nacos 相关
Nacos注册中心
版本清单
spring-boot 3.3.4
spring-cloud 2023.0.3
spring-cloud-alibaba 2023.0.3.2
nacos 2.3.2
nacos 软件安装
github.com/alibaba/nac…
nacos-server-{version}.zip(Windows 推荐)
nacos-server-{version}.tar.gz(Linux/macOS 推荐)
启动|停用Nacos服务
打开终端(Terminal),通过 cd 命令进入Nacos解压目录下的 bin 文件夹,然后执行启动命令。
# 进入Nacos的bin目录,注意替换路径为你的实际解压位置
cd /你的Nacos解压路径/nacos/bin
# 执行单机模式启动命令
sh startup.sh -m standalone
打开浏览器,访问 `http://localhost:8848/nacos/`。默认的用户名和密码均为 nacos
# 进入Nacos的bin目录
cd /你的Nacos解压路径/nacos/bin
# 执行停止脚本
sh shutdown.sh
项目目录结构


<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
关键代码
service-order service-product拥有上述依赖之后,application.properties写入订阅nacos服务地址。再次启动 service-order service-product之后,就能看到在nacos服务列表中看到这两个服务了。
spring.application.name=service-product
server.port=9000
spring.cloud.nacos.server-addr=127.0.0.1:8848
@Configuration
public class RestTemplateConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
service-order【OrderServiceImpl】添加调用service-product服务的请求
package org.example.order.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.example.model.Order;
import org.example.model.Product;
import org.example.order.service.IOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal;
import java.util.List;
@Slf4j
@Service
public class OrderServiceImpl implements IOrderService {
@Autowired
private RestTemplate restTemplate;
@Override
public Order createOrder(Long productId, Long userId) {
Product product = getProductBalancedAnnotation(productId);
Order order = new Order();
order.setId(1L);
order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));
order.setUserId(userId);
order.setNickName("小明");
order.setAddress("成都");
order.setProducts(List.of(product));
return order;
}
private Product getProductBalancedAnnotation(Long productId) {
String url = "http://service-product/product/getProduct/" + productId;
log.info("发送远程请求:{}", url);
Product product = restTemplate.getForObject(url, Product.class);
return product;
}
}
service-product controller层的请求处理
package org.example.product.controller;
import lombok.extern.slf4j.Slf4j;
import org.example.model.Product;
import org.example.product.service.IProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RequestMapping("/product")
@RestController
public class ProductController {
@Autowired
private IProductService productService;
@GetMapping("/getProduct/{id}")
public Product getProduct(@PathVariable("id") Long id) {
log.info("server-product 接收到请求:productId:{}", id);
return productService.getProductById(id);
}
}