苍穹外卖项目改造规范计划:微服务架构+nacos

一、前提背景:为什么要做微服务拆分?

1. 单体架构的核心痛点

之前项目采用单体Spring Boot架构,所有功能(用户端、管理端)耦合在一个服务中,随着业务迭代暴露以下问题:

  • 资源浪费:高频功能(如购物车、下单)与低频功能(如地址簿修改)共享资源,高负载场景无法独立扩容;
  • 故障扩散:一个模块异常(如购物车代码BUG)可能导致整个系统不可用;
  • 迭代低效:用户端(C端)和管理端(B端)需求节奏不同(C端侧重体验,B端侧重运营),却需同步发版;
  • 维护复杂:代码量持续膨胀,模块边界模糊,新功能开发、问题排查效率越来越低。

2. 拆分核心逻辑

遵循「场景+负载」双维度拆分原则:

  • 高频高负载场景(如订单、购物车):独立部署,保障性能和扩容灵活性;
  • 低频低负载场景(如用户地址簿、员工基础管理):聚合部署,避免资源闲置;
  • 功能关联性强的场景(如商品查询类功能):集中管理,便于统一优化(如缓存、数据库操作);
  • 业务域隔离(C端/B端分离):避免功能混淆,迭代互不影响。

二、微服务模块拆分方案(按业务域+负载分层)

1. 模块全景图(6个业务服务+2个公共依赖)

服务名称 业务域 核心功能 拆分原因 技术栈核心依赖
sky-cart-service C端-购物车 商品增删改、购物车清空、购物车查询 高频高负载,需独立扩容;与下单逻辑解耦,故障不影响核心交易 Spring Boot、Nacos Discovery、Redis
sky-order-service C端-订单 下单、催单、订单支付、状态变更(取消/确认/派送)、历史订单查询 核心交易场景,高负载+复杂逻辑;故障隔离,仅影响下单流程 Spring Boot、Nacos Discovery、MySQL
sky-user-base-service C端-用户基础 用户登录/登出、微信注册、地址簿管理(增删改查) 低频场景聚合,负载低;功能关联性强,维护高效 Spring Boot、Nacos Discovery、MySQL
sky-user-goods-query-service C端-商品查询 套餐/菜品查询(列表/详情)、分类查询、店铺营业状态查询 纯查询(读多写少),集中做缓存优化;减少重复查询逻辑,降低数据库压力 Spring Boot、Nacos Discovery、Redis
sky-admin-order-service B端-管理订单 订单筛选、接单/拒单/派送、订单详情查询、运营数据统计 B端高负载功能;与C端订单逻辑隔离(C端创单,B端运营) Spring Boot、Nacos Discovery、MySQL
sky-admin-operation-service B端-基础运营 员工管理、菜品/套餐/分类管理、店铺管理、文件上传、工作台统计 低负载聚合;均为平台基础运营功能,关联紧密,运维高效 Spring Boot、Nacos Discovery、MySQL
sky-common 公共依赖 通用工具类、异常处理、常量定义、全局返回结果(Result)、JWT工具 统一复用,避免重复编码;规范各服务输出格式 Spring Boot、lombok、fastjson
sky-pojo 公共依赖 所有服务共享的实体类(Entity)、DTO、VO、枚举类 统一数据模型,避免各服务实体不一致导致的兼容性问题 无(纯POJO,仅依赖lombok)

2. 架构层级图(Mermaid语法,可直接复制渲染)

flowchart TD subgraph 客户端层 C1[用户端APP/小程序] C2[管理端Web后台] end subgraph 网关层 G[sky-server-gateway 网关统一入口] end subgraph 业务服务层-C端 S1[sky-cart-service 购物车服务] S2[sky-order-service 订单服务] S3[sky-user-base-service 用户基础服务] S4[sky-user-goods-query-service 商品查询服务] end subgraph 业务服务层-B端 S5[sky-admin-order-service 管理端订单服务] S6[sky-admin-operation-service 管理端运营服务] end subgraph 公共依赖层 P1[sky-common 通用工具层] P2[sky-pojo 共享实体层] end subgraph 存储层 DB[MySQL 业务数据库] R[Redis 缓存/购物车] OSS[阿里云OSS 文件存储] end %% 依赖关系 C1 --> G C2 --> G G --> S1 G --> S2 G --> S3 G --> S4 G --> S5 G --> S6 S1 --> P1 S1 --> P2 S2 --> P1 S2 --> P2 S3 --> P1 S3 --> P2 S4 --> P1 S4 --> P2 S5 --> P1 S5 --> P2 S6 --> P1 S6 --> P2 S1 --> R S2 --> DB S2 --> R S3 --> DB S4 --> DB S4 --> R S5 --> DB S6 --> DB S6 --> OSS

3. 服务依赖关系说明

  • 所有业务服务均依赖 sky-commonsky-pojo,无需重复编写通用逻辑;
  • 网关(sky-server-gateway)不依赖任何业务服务,仅通过Nacos发现服务并转发请求;
  • 业务服务之间禁止直接依赖(如订单服务不直接调用购物车服务),需通过“服务调用+事件驱动”(后续可集成OpenFeign+RocketMQ)实现通信。

三、核心配置方案

1. 前置准备:Nacos环境初始化

(1)命名空间规划(隔离环境)

在Nacos控制台创建3个命名空间,记录ID备用:

命名空间名称 用途 命名空间ID(填写自己的)
dev 开发环境 你的dev环境命名空间ID
test 测试环境 你的test环境命名空间ID
prod 生产环境 你的prod环境命名空间ID

(2)分组规划(同一环境内业务隔离)

业务域 分组名称 包含服务
C端-购物车 sky-group-cart sky-cart-service
C端-订单 sky-group-order sky-order-service
C端-用户相关 sky-group-user sky-user-base-service、sky-user-goods-query-service
B端-管理相关 sky-group-admin sky-admin-order-service、sky-admin-operation-service
网关 (无需单独分组) 订阅所有业务分组

2. 父pom.xml(统一依赖版本,避免冲突)

项目根目录pom.xml添加依赖管理,所有服务继承此父pom:

<?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>

    <groupId>com.sky</groupId>
    <artifactId>sky-take-out</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <!-- 所有业务服务模块 -->
        <module>sky-cart-service</module>
        <module>sky-order-service</module>
        <module>sky-user-base-service</module>
        <module>sky-user-goods-query-service</module>
        <module>sky-admin-order-service</module>
        <module>sky-admin-operation-service</module>
        <module>sky-server-gateway</module>
        <!-- 公共依赖模块 -->
        <module>sky-common</module>
        <module>sky-pojo</module>
    </modules>

    <!-- 统一依赖版本管理 -->
    <dependencyManagement>
        <dependencies>
            <!-- Spring Boot 基础版本 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.7.3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- Spring Cloud 版本(适配Boot 2.7.3) -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2021.0.4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- Spring Cloud Alibaba 版本(适配Cloud 2021.0.4) -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2021.0.4.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 公共模块版本 -->
            <dependency>
                <groupId>com.sky</groupId>
                <artifactId>sky-common</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <dependency>
                <groupId>com.sky</groupId>
                <artifactId>sky-pojo</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

3. 业务服务通用配置(以sky-order-service为例)

(1)application.yml(通用配置)

spring:
  application:
    name: sky-order-service  # 服务名(网关路由必须用此名称)
  profiles:
    active: ${SPRING_PROFILES_ACTIVE:dev}  # 环境变量优先,默认dev
  cloud:
    nacos:
      # Nacos服务发现配置
      discovery:
        server-addr: ${NACOS_SERVER_ADDR:你的Nacos地址:8848}  # 本地Nacos地址,生产环境用环境变量覆盖
        username: ${NACOS_USERNAME:你的Nacos用户名}  # 自己的Nacos登录用户名
        password: ${NACOS_PASSWORD:你的Nacos密码}  # 自己的Nacos登录密码
        namespace: ${NACOS_NAMESPACE:你的dev环境命名空间ID}  # 填写dev环境命名空间ID
        group: sky-group-order  # 对应业务分组

(2)application-dev.yml(开发环境配置)

server:
  port: 8082  # 每个服务端口唯一(避免冲突)
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://你的MySQL地址:3306/sky_take_out_order?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    username: 你的MySQL用户名
    password: 你的MySQL密码
  redis:
    host: 你的Redis地址
    port: 6379
    database: 2  # 每个服务用独立的Redis数据库编号(避免key冲突)
    password: 你的Redis密码(无则留空)
    timeout: 3000ms

4. 网关配置(sky-server-gateway

(1)pom.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>
    <parent>
        <groupId>com.sky</groupId>
        <artifactId>sky-take-out</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.sky</groupId>
    <artifactId>sky-server-gateway</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- Gateway核心依赖(WebFlux,禁止加spring-boot-starter-web) -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- Nacos服务发现 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- 负载均衡组件(lb://协议必须) -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <!-- 公共模块 -->
        <dependency>
            <groupId>com.sky</groupId>
            <artifactId>sky-common</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sky</groupId>
            <artifactId>sky-pojo</artifactId>
        </dependency>
    </dependencies>
</project>

(2)application.yml(路由规则+Nacos配置)

spring:
  application:
    name: sky-server-gateway
  profiles:
    active: ${SPRING_PROFILES_ACTIVE:dev}
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_SERVER_ADDR:你的Nacos地址:8848}
        username: ${NACOS_USERNAME:你的Nacos用户名}
        password: ${NACOS_PASSWORD:你的Nacos密码}
        namespace: ${NACOS_NAMESPACE:你的dev环境命名空间ID}
        # 网关订阅所有业务分组(逗号分隔)
        group: sky-group-cart,sky-group-order,sky-group-user,sky-group-admin
    gateway:
      # 路由规则(按业务域划分)
      routes:
        # 1. C端-购物车路由
        - id: cart-service-route
          uri: lb://sky-cart-service  # 对应购物车服务名
          predicates:
            - Path=/api/cart/**  # 前端请求路径前缀
          filters:
            - StripPrefix=1  # 去掉前缀/api,转发到/cart/**
        # 2. C端-订单路由
        - id: order-service-route
          uri: lb://sky-order-service
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1
        # 3. C端-用户基础路由
        - id: user-base-service-route
          uri: lb://sky-user-base-service
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1
        # 4. C端-商品查询路由
        - id: goods-query-service-route
          uri: lb://sky-user-goods-query-service
          predicates:
            - Path=/api/goods/**
          filters:
            - StripPrefix=1
        # 5. B端-管理订单路由
        - id: admin-order-service-route
          uri: lb://sky-admin-order-service
          predicates:
            - Path=/admin/order/**
          filters:
            - StripPrefix=1
        # 6. B端-基础运营路由
        - id: admin-operation-service-route
          uri: lb://sky-admin-operation-service
          predicates:
            - Path=/admin/**  # 运营后台请求前缀(与其他路由不冲突)

(3)启动类(com.sky.gateway.SkyGatewayApplication

package com.sky.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * 网关启动类:排除Redis自动配置(网关无需直接操作Redis)
 * 禁止添加@EnableWebMvc(与WebFlux冲突)
 */
@SpringBootApplication(exclude = {RedisAutoConfiguration.class})
@EnableDiscoveryClient
public class SkyGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(SkyGatewayApplication.class, args);
    }
}

5. 公共模块配置(sky-common示例)

pom.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>
    <parent>
        <groupId>com.sky</groupId>
        <artifactId>sky-take-out</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.sky</groupId>
    <artifactId>sky-common</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- Spring Boot基础依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- 工具类 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>
        <!-- JWT工具 -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <!-- 异常处理 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <scope>provided</scope>  <!-- 仅提供编译支持,避免与网关WebFlux冲突 -->
        </dependency>
    </dependencies>
</project>

四、避坑指南:避免“服务找不到”“配置冲突”的核心原则

  1. Nacos隔离三要素:所有服务(含网关)必须满足「同一命名空间+网关订阅对应分组+服务名完全一致」,否则服务不可见;
  2. 端口唯一:每个业务服务的server.port必须不同(如购物车8081、订单8082、用户基础8083),避免端口占用;
  3. 依赖冲突:网关禁止引入spring-boot-starter-web(与WebFlux冲突),业务服务按需引入;
  4. Redis数据库隔离:不同服务使用不同的Redisdatabase编号(如购物车用1、订单用2),避免key覆盖;
  5. 启动顺序:必须按「Nacos → 公共模块(install到本地仓库) → 业务服务 → 网关」启动,否则网关启动时找不到业务服务。

五、方案优势与后续扩展

1. 方案优势

  • 可扩展性:高负载服务(如订单、购物车)支持独立扩容,应对流量峰值;
  • 稳定性:故障隔离,单个服务异常不影响全局;
  • 维护性:业务域边界清晰,迭代高效,新功能可快速新增服务(如后续新增支付服务sky-payment-service);
  • 通用性:配置方案标准化,新增服务可直接复制现有模板修改。

2. 后续扩展方向

  • 服务通信:集成OpenFeign实现服务间同步调用(如订单服务调用购物车服务清空数据);
  • 分布式事务:引入Seata解决跨服务事务问题(如订单创建+库存扣减);
  • 熔断降级:集成Sentinel避免服务雪崩(如高并发下保护订单服务);
  • 监控告警:集成Prometheus+Grafana监控服务状态,配置告警规则。

总结

本方案基于「业务域+负载」双维度拆分微服务,通过Nacos的「命名空间+分组」实现环境隔离与业务隔离,网关统一入口转发请求,既解决了单体架构的痛点,又保障了微服务的可扩展性和稳定性。所有配置均已替换为占位符,无任何敏感信息,复制粘贴后只需填入自己的环境信息(Nacos地址、数据库密码等)即可快速落地,后续新增服务遵循此规范即可无缝集成。

posted @ 2025-11-30 13:36  WILK  阅读(1)  评论(0)    收藏  举报