spring cloud

4 阅读4分钟

架构

单体架构

deepseek_mermaid_20260412_9d8367.png

ALL IN ONE 单体架构意味着:
  • 单一部署单元:所有功能模块(商品、订单、用户、支付、物流等)都打包在一个Java项目里。
  • 共享环境:这些模块运行在同一个JVM进程、同一台服务器上,并通常连接同一个数据库。
优点
优点具体说明
开发简单单一项目,IDE管理方便,调试容易,无需考虑服务间调用。
测试容易只需启动一个应用即可进行端到端测试。
部署单一只需部署一个JAR/WAR包,运维成本低。
事务管理简单所有模块共享一个数据库,利用本地事务(@Transactional)即可保证ACID。
缺点
缺点具体表现
并发能力受限整个应用只能整体横向扩展(增加多个相同副本),无法针对高并发的商品模块单独扩容。
可靠性差一个模块(如支付)的内存泄漏或死锁,会导致整个应用崩溃。
维护成本递增代码量巨大(数百万行),不同模块代码耦合,修改一处可能影响全局,IDE编译变慢。
技术选型锁死所有模块共用技术栈(如Java版本、框架版本),无法为不同场景选择合适工具。
集群架构

deepseek_mermaid_20260412_034915.png 把同一个应用部署在多台服务器上,通过负载均衡将用户请求分发到不同的服务器

  • ✅ 集群架构解决了什么
单体架构的问题集群架构的解决方案
单点故障 → 应用崩溃则服务全挂一台服务器宕机,负载均衡将流量切到其他节点
无法应对高并发 → 单一JVM处理能力有限水平扩展:增加服务器节点即可提升吞吐量
数据库压力大 → 所有请求读写同一库读写分离:主库写、从库读,分摊压力

  • ❌ 集群架构仍存在的问题
问题说明
代码依然耦合所有模块(商品、订单、支付)仍在同一个项目里,修改一个模块需要重新部署整个集群
数据库仍是瓶颈虽然做了读写分离,但单张表数据量过大时,主库写入压力依然集中
session共享问题用户登录后请求落到不同服务器,需要引入Redis等中间件共享session
分布式事务涉及多个模块的写操作(如下单扣库存),单体本地事务不再适用,需要分布式事务方案
分布式微服务架构
分布式

我们按照业务拆分,每个模块又叫微服务,可以独立的开发,测试,部署,升级,扩展。
数据库同样可以根据业务拆分,每个数据库只存储一部分数据。

image.png

部署架构

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

image.png

核心组件说明
组件作用你的笔记对应
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

项目目录结构

image.png

acadc9a4cf1e0e0d520d06b0164ecfcd.jpg

  • 关键的pom.xml [service模块]
<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
  • service-order添加配置
@Configuration
public class RestTemplateConfig {

    /**
     * RestTemplate是spring提供的线程安全的http客户端,用于发送http请求
     */
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
  • service-orderOrderServiceImpl】添加调用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;
    }

    /**
     * 远程调用获取商品信息 - @LoadBalanced注解实现负载均衡
     */
    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);
    }
}