Spring Cloud Alibaba 微服务全栈落地实战手册

0 阅读21分钟

1 技术栈整体选型(企业稳定版)

本手册全套采用企业生产稳定版本,基于 SpringBoot3.x + JDK21 最新生态搭建,所有框架、中间件版本经过兼容性适配,彻底规避版本冲突、功能失效、线上兼容报错等问题,完全适配中小型企业微服务生产落地场景,新手可直接照搬使用。

所有技术选型兼顾稳定性、高性能、易维护、低学习成本,摒弃老旧淘汰组件,统一技术规范,适配后续架构扩容与迭代。

  • 基础核心框架:SpringBoot 3.2.5、SpringCloud 2023.0.1、SpringCloudAlibaba 2023.0.1.0(官方适配稳定组合)

  • 微服务治理组件:Nacos 2.3.2、Sentinel 1.8.8、Dubbo 3.2.9(服务注册、容错、RPC调用全套治理)

  • 分布式事务:Seata 1.7.1(支持AT无侵入、TCC高精度两种模式)

  • 消息中间件:RocketMQ 4.9.7(业务解耦)、Kafka 3.6.1(高吞吐日志采集)

  • 多层数据存储:MySQL 8.0(主从分库分表)、Redis 7.2(缓存)、ES 8.13(全文检索)、MongoDB 7.0(非结构化数据)、Sharding-JDBC 5.4.1(分片存储)

  • 工作流引擎:Flowable 7.2.0(适配各类审批业务)

  • 权限认证框架:Sa-Token 1.37.0(主力轻量鉴权)、Spring Security 6.2.4(辅助OAuth2授权)

  • 持久层框架:MyBatis-Flex 1.7.5(极简CRUD、无需手写SQL)

  • 部署运维架构:Docker、K8s 1.29、Nginx 1.24(容器化、负载均衡全套)

  • 缓存与文件存储:Caffeine 3.1.8(本地高性能缓存)、阿里云OSS(大文件存储)

  • 监控链路体系:Prometheus、Grafana、SkyWalking、ELK(全链路监控、日志归集)

  • 工程规范组件:SonarQube(代码检测)、XXL-Job(分布式定时任务)

2 项目架构与工程搭建(标准化分层)

本项目采用标准化微服务分层架构,按业务职责、技术能力拆分独立模块,统一父工程版本依赖,解决传统单体项目耦合严重、依赖混乱、难以维护、无法独立扩容的问题,结构清晰,小白可快速理解各模块作用。

2.1 工程模块拆分(各司其职)

所有模块职责单一、互不冗余,公共能力统一抽离,业务模块独立开发部署,方便迭代维护。

# 微服务整体工程结构
micro-cloud-alibaba
├── micro-common        // 全局公共模块:工具类、常量、统一异常、返回体、通用配置
├── micro-gateway       // 统一网关入口:路由转发、限流、跨域、权限拦截
├── micro-system        // 基础系统服务:用户、角色、权限、字典、登录认证
├── micro-order         // 核心业务服务:订单创建、订单查询、订单状态管理
├── micro-storage       // 库存业务服务:商品库存扣减、库存查询、库存冻结
├── micro-message       // 消息推送服务:MQ消息收发、短信、站内信通知
├── micro-workflow      // 工作流专属服务:各类审批流程发起、审批、驳回
├── micro-file          // 文件服务:OSS上传、下载、分片上传、文件管理
├── micro-devops        // 运维配置:Docker、K8s、CI/CD配置文件
└── micro-monitor       // 监控服务:链路追踪、指标监控、日志归集

2.2 父工程统一依赖管理(根治版本冲突)

通过父工程统一管控所有框架、中间件版本,子模块无需重复定义版本,从根源避免依赖冲突、版本不匹配问题,新手无需手动适配版本。

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.micro.cloud</groupId>
    <artifactId>micro-cloud-alibaba</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <name>微服务父工程</name>

    <!-- 全局统一版本配置 -->
    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <spring.boot.version>3.2.5</spring.boot.version>
        <spring.cloud.version>2023.0.1</spring.cloud.version>
        <spring.cloud.alibaba.version>2023.0.1.0</spring.cloud.alibaba.version>
        <mybatis.flex.version>1.7.5</mybatis.flex.version>
        <sa.token.version>1.37.0</sa.token.version>
    </properties>

    <!-- 统一依赖版本管控,子模块直接引用无需写版本 -->
    <dependencyManagement>
        <dependencies>
            <!-- SpringBoot 全家桶统一依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- SpringCloud 微服务核心依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- SpringCloudAlibaba 组件统一依赖 -->
            <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>
</project>

3 Nacos 服务注册发现与配置中心

Nacos 是微服务核心基础组件,一站式替代传统 Eureka(注册发现)+ Config(配置中心),实现服务自动注册、心跳检测、故障节点剔除、配置动态刷新,大幅简化微服务治理难度,新手开箱即用。测试可用单机,生产必须集群部署保障高可用

3.1 核心依赖引入(所有业务模块通用)

所有微服务业务模块只需引入以下两个依赖,即可拥有注册发现和配置中心能力。

<!-- Nacos 服务注册与发现:让服务互相感知、远程调用 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!-- Nacos 配置中心:统一管理配置、动态刷新无需重启服务 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

3.2 生产级配置文件(bootstrap.yml)

使用 bootstrap.yml 优先加载Nacos配置(优先级高于application.yml),配置心跳优化、公共配置共享、动态刷新,适配生产集群场景,小白直接修改地址即可使用。

# Nacos生产级配置
spring:
  application:
    name: micro-order  # 当前服务名称(Nacos注册名称,唯一标识)
  cloud:
    nacos:
      # 服务注册发现配置
      discovery:
        server-addr: 127.0.0.1:8848  # Nacos服务地址
        heartbeat-interval: 5000     # 心跳上报间隔:5秒(主动上报存活)
        heartbeat-timeout: 15000     # 心跳超时时间:15秒(超时判定服务死亡)
        enabled: true                # 开启服务注册发现
      # 配置中心配置
      config:
        server-addr: 127.0.0.1:8848  # Nacos配置中心地址
        file-extension: yml          # 配置文件格式
        # 公共配置共享:所有服务通用配置统一抽取,无需每个服务重复配置
        shared-configs[0]:
          data-id: micro-common.yml
          refresh: true              # 公共配置支持动态刷新
        refresh-enabled: true         # 开启配置动态刷新(改配置不用重启服务)

3.3 启动类开启注册注解

只需在服务启动类添加注解,即可自动完成服务注册,无需多余复杂配置。

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

// 微服务启动核心注解
@SpringBootApplication
@EnableDiscoveryClient  // 开启Nacos服务注册与发现
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

生产核心要点(必看):1、单机Nacos仅用于本地测试,生产环境必须搭建集群防止单点故障;2、数据库密码、密钥等敏感配置,必须使用Nacos加密配置,禁止代码明文硬编码;3、所有服务统一通过Nacos托管配置,告别本地配置混乱。

4 Sentinel 流量控制与服务容错

微服务调用存在级联故障风险,单服务卡顿、超时会导致整体服务雪崩。Sentinel 专为微服务容错设计,通过限流、熔断、降级三大核心能力,拦截异常流量、隔离故障服务,保证系统整体稳定,配置简单、可视化操作,新手易上手。

4.1 依赖引入

<!-- Sentinel 微服务限流熔断容错核心依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

4.2 生产级配置(规则持久化)

默认Sentinel规则保存在内存,服务重启规则丢失。生产环境将规则持久化到Nacos,永久生效,支持动态修改。

spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080  # Sentinel控制台地址
        port: 8719                  # 客户端监控端口(默认无需修改)
      eager: true                   # 提前初始化Sentinel,避免首次请求拦截
      # 限流规则持久化到Nacos
      datasource:
        flow:
          nacos:
            server-addr: 127.0.0.8848
            data-id: sentinel-flow-rule
            rule-type: flow

4.3 自定义降级兜底实现(小白通用模板)

区分限流熔断兜底(系统流量问题)业务异常兜底(代码逻辑问题),避免全局异常覆盖容错逻辑,适配所有业务接口。

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

    // 标记需要限流熔断的核心接口
    // blockHandler:流量超限、熔断触发兜底
    // fallback:业务代码报错触发兜底
    @SentinelResource(value = "createOrder", blockHandler = "createOrderBlockHandler", fallback = "createOrderFallback")
    public String createOrder(Long userId) {
        // 核心下单业务逻辑
        return "订单创建成功";
    }

    /**
     * 限流、熔断兜底方法(系统流量异常、服务故障)
     * 参数必须和原方法一致,最后追加BlockException参数
     */
    public String createOrderBlockHandler(Long userId, BlockException e) {
        return "系统繁忙,请稍后重试";
    }

    /**
     * 业务异常降级兜底方法(代码报错、逻辑异常)
     */
    public String createOrderFallback(Long userId) {
        return "订单服务异常,暂时无法下单,请稍后重试";
    }
}

生产核心要点:1、所有核心下单、支付、查询接口必须配置QPS限流;2、严格区分两种兜底场景,避免异常提示混乱;3、大流量场景开启链路限流,防止下游服务被打垮。

5 Dubbo 高性能RPC远程调用

Dubbo3 是微服务高性能远程调用框架,替代传统Feign调用方式,基于Triple协议,支持HTTP2、流式调用,吞吐量更高、延迟更低、兼容性更强,是企业微服务跨服务调用首选方案,结构简单、调用直观。

5.1 核心依赖引入

<!-- Dubbo3 高性能RPC远程调用依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-dubbo</artifactId>
</dependency>

5.2 服务提供者实现(被调用方)

公共接口统一放在common公共模块,所有服务可依赖引用;实现类通过注解暴露服务,指定版本方便迭代兼容。

// 1、公共接口(存放于micro-common模块,所有服务共享)
public interface StorageDubboService {
    // 库存扣减接口
    boolean deductStorage(Long goodsId, Integer count);
}
// 2、服务实现类(库存服务micro-storage模块)
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;

// 暴露Dubbo服务,指定版本,方便后续迭代升级
@DubboService(version = "1.0.0")
@Service
public class StorageDubboServiceImpl implements StorageDubboService {

    // 实现库存扣减业务逻辑
    @Override
    public boolean deductStorage(Long goodsId, Integer count) {
        // 执行库存查询、扣减逻辑
        return true;
    }
}

5.3 服务消费者调用(调用方)

通过注解直接注入远程服务,像调用本地方法一样调用远程接口,极简用法。

import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

@Service
public class OrderBizService {

    // 引用远程Dubbo服务,指定对应版本、负载均衡策略
    @DubboReference(version = "1.0.0", loadbalance = "roundrobin")
    private StorageDubboService storageDubboService;

    // 下单业务,远程调用库存服务
    public void createOrder() {
        // 远程调用库存扣减,无需手动写HTTP请求
        boolean result = storageDubboService.deductStorage(1001L, 1);
    }
}

5.4 生产级Dubbo全局配置

# Dubbo生产配置
dubbo:
  application:
    name: micro-order-dubbo  # 当前Dubbo服务名称
  protocol:
    name: tri                # 使用Triple高性能协议
    port: -1                 # 自动分配端口,避免冲突
  registry:
    address: nacos://127.0.0.1:8848  # 注册到Nacos
  consumer:
    timeout: 3000            # 消费者调用超时3秒
    retries: 1               # 失败重试1次(读接口可用,写接口慎用)
  provider:
    timeout: 3000            # 服务提供者超时时间

生产核心要点:1、所有Dubbo服务必须指定版本,接口迭代通过版本区分,不影响旧业务;2、新增、修改、删除等写接口禁止重试,避免重复数据;3、查询接口可配置少量重试,提升容错性。

6 Seata 分布式事务落地(AT/TCC)

微服务跨服务调用时,不同服务数据库独立,会出现数据不一致问题(比如订单创建成功、库存扣减失败)。Seata 专门解决分布式事务问题,提供两种主流模式:AT模式(无侵入、简单通用)TCC模式(高精度、适配复杂业务)

6.1 核心依赖引入

<!-- Seata 分布式事务核心依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

6.2 AT模式(无侵入、小白首选)

适用于90%常规增删改业务,无需手动编写事务回滚代码,Seata自动记录undo日志,异常自动回滚,零侵入、上手极快。前置要求:所有业务库必须初始化undo_log数据表

import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.stereotype.Service;

@Service
public class OrderTxService {

    // 开启全局分布式事务:任意步骤异常,全部回滚
    @GlobalTransactional(rollbackFor = Exception.class)
    public void createOrderTx() {
        // 1、本地事务:创建订单
        orderMapper.insert(order);
        // 2、远程事务:调用Dubbo扣减库存
        storageDubboService.deductStorage(1001L,1);
        // 模拟异常:触发全局事务回滚,订单、库存全部复原
        int i = 1/0;
    }
}

6.3 TCC模式(高精度复杂事务)

适用于库存冻结、资金预扣、积分变动等高精度业务,手动控制三阶段事务,保证数据绝对一致,需严格遵守幂等、空回滚、防悬挂三大规则。

import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.LocalTCC;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;

// 开启本地TCC事务模式
@LocalTCC
public interface StorageTccService {

    /**
     * 第一阶段 Try:资源检查+资源冻结
     * 冻结库存,不真正扣减,防止超卖
     */
    @TwoPhaseBusinessAction(name = "storageTcc", commitMethod = "commit", rollbackMethod = "rollback")
    boolean tryDeduct(BusinessActionContext context,
                      @BusinessActionContextParameter(paramName = "goodsId") Long goodsId,
                      @BusinessActionContextParameter(paramName = "count") Integer count);

    /**
     * 第二阶段 Confirm:确认提交
     * 业务正常,真正扣减冻结库存
     */
    boolean commit(BusinessActionContext context);

    /**
     * 第二阶段 Cancel:事务回滚
     * 业务异常,解冻库存,恢复数据
     */
    boolean rollback(BusinessActionContext context);
}

生产核心要点:1、AT模式必须提前创建undo_log表,否则事务失效;2、大事务拆分为小事务,避免锁超时;3、TCC三阶段方法必须实现幂等性,防止重复执行导致数据错乱。

7 消息中间件(RocketMQ/Kafka)实战

消息中间件核心作用:业务解耦、流量削峰、异步通知,避免同步调用卡顿、接口超时。RocketMQ侧重业务可靠投递,Kafka侧重高吞吐日志采集,按需选用,生产核心是保证消息不丢、不重复、可靠消费。

7.1 RocketMQ 业务实战(业务解耦首选)

依赖引入

<!-- RocketMQ 消息队列依赖(SpringCloud Stream标准化用法) -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>

可靠消息生产者(保证消息不丢)

import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

@Service
public class MqProducerService {
    @Resource
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 发送订单消息(异步可靠投递)
     * 发送失败自动记录日志,可后续重试,杜绝消息丢失
     */
    public void sendOrderMsg(OrderDTO orderDTO) {
        rocketMQTemplate.asyncSend("order-topic",
                MessageBuilder.withPayload(orderDTO).build(),
                result -> {
                    // 回调监听:判断消息是否发送成功
                    if (!result.isSendStatus()) {
                        // 投递失败:日志记录、入库、告警、后续重试
                    }
                });
    }
}

幂等消费者(杜绝重复消费)

MQ消息可能重复投递,必须做幂等校验,保证同一消息只处理一次。

import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Service;

@Service
public class OrderMsgConsumer {

    // 监听订单消息队列
    @StreamListener("order-topic-input")
    public void consume(Message<OrderDTO> message) {
        OrderDTO order = message.getPayload();
        // 幂等核心:根据订单唯一编号判断是否已处理
        if (orderMapper.exists(order.getOrderNo())) {
            // 已处理直接跳过,杜绝重复消费
            return;
        }
        // 执行业务消费逻辑:订单状态更新、消息通知等
    }
}

7.2 Kafka 高吞吐实战(日志、大数据场景首选)

Kafka主打超高吞吐,适合日志采集、数据流同步、批量消息推送,生产必须手动提交offset、保证消费幂等。

依赖引入

<!-- Kafka 高吞吐消息队列依赖 -->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>

生产级配置

spring:
  kafka:
    bootstrap-servers: 127.0.0.1:9092
    producer:
      acks: all                # 消息全部落盘才返回成功,保证不丢消息
      retries: 3               # 发送失败重试3次
      batch-size: 16384        # 批量发送大小,提升吞吐
      buffer-memory: 33554432
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
    consumer:
      group-id: micro-order-group
      enable-auto-commit: false # 关闭自动提交,手动提交保证消费可靠
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
      properties:
        spring.json.trusted.packages: "*"
    listener:
      ack-mode: manual_immediate # 消费成功手动提交offset

Kafka生产者工具类

import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import javax.annotation.Resource;

@Service
public class KafkaProducerService {
    @Resource
    private KafkaTemplate<String, Object> kafkaTemplate;

    // 通用消息发送方法
    public void sendMsg(String topic, Object data) {
        ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(topic, data);
        // 发送结果回调
        future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
            @Override
            public void onSuccess(SendResult<String, Object> result) {}

            @Override
            public void onFailure(Throwable ex) {
                // 发送失败:日志记录、入库重试、告警
            }
        });
    }
}

Kafka幂等消费者

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Service;

@Service
public class KafkaConsumerService {

    // 监听日志消息队列
    @KafkaListener(topics = "order-log-topic", groupId = "micro-order-group")
    public void consume(ConsumerRecord<String, String> record, Acknowledgment ack) {
        String value = record.value();
        // 幂等校验:根据消息唯一ID判断是否已消费
        String msgId = record.headers().lastHeader("msgId").value().toString();
        if (checkMsgExists(msgId)) {
            ack.acknowledge(); // 已消费直接提交偏移量
            return;
        }
        // 执行业务消费逻辑
        ack.acknowledge(); // 消费成功手动提交
    }

    // 查询Redis/数据库,判断消息是否已处理
    private boolean checkMsgExists(String msgId){
        return false;
    }
}

生产核心要点:所有消息必须配置幂等校验、失败重试、死信队列,异常消息不丢弃,保证消息最终一致性。

8 二级缓存架构(Caffeine+Redis)

采用本地Caffeine缓存+分布式Redis缓存二级架构,兼顾超高并发性能和集群数据一致性,同时彻底解决缓存穿透、击穿、雪崩三大线上高频问题,新手可直接复用工具类。

8.1 核心依赖

<!-- Caffeine 本地高性能缓存(性能远超Guava) -->
<dependency>
    <groupId>com.github.benmanes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.8</version>
</dependency>

<!-- Redis 分布式缓存 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

8.2 二级缓存通用工具类(可直接复用)

优先查询本地缓存,减少远程Redis请求,双缓存同步更新、同步删除,保证数据一致。

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Component
public class DoubleCacheUtil {
    // 本地缓存配置:最大1000条、写入5分钟过期
    private final Cache<String, Object> localCache = Caffeine.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(5, TimeUnit.MINUTES)
            .build();

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 查询缓存:优先本地,再分布式
     */
    public Object getCache(String key) {
        // 1、查本地缓存
        Object local = localCache.getIfPresent(key);
        if (local != null) {
            return local;
        }
        // 2、本地无数据,查询Redis
        Object redis = redisTemplate.opsForValue().get(key);
        if (redis != null) {
            localCache.put(key, redis);
            return redis;
        }
        return null;
    }

    /**
     * 同步更新双缓存
     */
    public void setCache(String key, Object value, long time, TimeUnit unit) {
        localCache.put(key, value);
        redisTemplate.opsForValue().set(key, value, time, unit);
    }

    /**
     * 同步删除双缓存
     */
    public void delCache(String key) {
        localCache.invalidate(key);
        redisTemplate.delete(key);
    }
}

8.3 缓存三大问题解决方案(生产必备)

全覆盖解决缓存穿透、击穿、雪崩问题,代码极简、小白可直接照搬。

// 1、防缓存穿透:缓存空值,避免频繁查询数据库
public Object getGoodsInfo(Long goodsId) {
    String key = "goods:" + goodsId;
    Object cache = doubleCacheUtil.getCache(key);
    if (cache != null) {
        return "null".equals(cache) ? null : cache;
    }
    // 查询数据库
    Goods goods = goodsMapper.selectById(goodsId);
    if (goods == null) {
        // 空值缓存60秒,防止穿透
        doubleCacheUtil.setCache(key, "null", 60, TimeUnit.SECONDS);
        return null;
    }
    // 随机过期时间,防止批量过期导致缓存雪崩
    long expire = 300 + (long)(Math.random() * 60);
    doubleCacheUtil.setCache(key, goods, expire, TimeUnit.SECONDS);
    return goods;
}

// 2、防缓存击穿:分布式锁控制热点Key
public Object getHotGoods(Long goodsId) {
    String key = "hot:goods:" + goodsId;
    Object cache = doubleCacheUtil.getCache(key);
    if (cache != null) {
        return cache;
    }
    // 加分布式锁,防止并发击穿
    String lockKey = "lock:goods:" + goodsId;
    boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, "lock", 3, TimeUnit.SECONDS);
    if (!lock) {
        // 未获取锁,自旋重试
        return getHotGoods(goodsId);
    }
    try {
        // 二次查缓存,避免重复查询数据库
        cache = doubleCacheUtil.getCache(key);
        if (cache != null) {
            return cache;
        }
        Goods goods = goodsMapper.selectById(goodsId);
        doubleCacheUtil.setCache(key, goods, 300, TimeUnit.SECONDS);
        return goods;
    } finally {
        // 释放锁
        redisTemplate.delete(lockKey);
    }
}

9 多层数据存储架构实践

针对不同业务数据特性,采用差异化存储方案:MySQL存核心结构化数据、分库分表应对大数据量、ES做全文检索、MongoDB存日志非结构化数据,各司其职,最大化性能。

9.1 Sharding-JDBC 分库分表配置

解决单表数据量过大、查询缓慢问题,按用户ID分片,均匀分摊数据压力。

spring:
  shardingsphere:
    datasource:
      names: ds0,ds1
      ds0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/db0
        username: root
        password: 123456
      ds1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/db1
        username: root
        password: 123456
    rules:
      sharding:
        tables:
          # 订单表分表规则
          t_order:
            actual-data-nodes: ds0.t_order_0,ds0.t_order_1,ds0.t_order_2,ds0.t_order_3,ds1.t_order_0,ds1.t_order_1,ds1.t_order_2,ds1.t_order_3
            table-strategy:
              standard:
                sharding-column: user_id  # 分片键
                sharding-algorithm-name: table-inline
        sharding-algorithms:
          table-inline:
            type: INLINE
            props:
              algorithm-expression: t_order_${user_id % 4}

9.2 MyBatis-Flex 极简高效查询

无需手写SQL,链式调用实现CRUD,大幅提升开发效率,小白零学习成本。

import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.stereotype.Repository;
import java.util.List;

@Repository
public interface OrderMapper extends BaseMapper<Order> {
    // 极简链式查询,无SQL、无硬编码
    default List<Order> listUserOrder(Long userId) {
        return selectList(QueryWrapper.create()
                .eq(Order::getUserId, userId)    // 等值条件
                .orderBy(Order::getCreateTime, false) // 时间倒序
                .limit(10)); // 分页限制
    }
}

9.3 ElasticSearch 全文检索

弥补MySQL模糊查询性能短板,实现订单、商品关键词模糊检索、高亮展示,适配搜索类业务。

依赖引入

<!-- ES 全文检索依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

ES配置

spring:
  elasticsearch:
    uris: http://127.0.0.1:9200
    username: elastic
    password: 123456

检索代码实现

// ES索引实体类
@Data
@Document(indexName = "order_info")
public class OrderES {
    @Id
    private String orderNo;
    private Long userId;
    private String goodsName;
    private Integer status;
    private LocalDateTime createTime;
}

// ES检索业务实现
@Service
public class OrderEsService {
    @Resource
    private ElasticsearchRestTemplate restTemplate;

    // 关键词分页检索+高亮展示
    public Page<OrderES> searchOrder(String keyword, int pageNum, int pageSize) {
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        // 多字段模糊匹配
        queryBuilder.withQuery(QueryBuilders.multiMatchQuery(keyword, "orderNo","goodsName"));
        // 关键词高亮标红
        HighlightBuilder highlight = new HighlightBuilder()
                .field("goodsName")
                .preTags("<span style='color:red'>")
                .postTags("</span>");
        queryBuilder.withHighlightBuilder(highlight);
        // 分页
        queryBuilder.withPageable(PageRequest.of(pageNum-1, pageSize));
        SearchHits<OrderES> hits = restTemplate.search(queryBuilder.build(), OrderES.class);
        return new PageImpl<>(hits.stream().toList(), PageRequest.of(pageNum-1,pageSize), hits.getTotalHits());
    }
}

9.4 MongoDB 非结构化数据存储

用于存储操作日志、用户行为记录、临时数据,无需建表,适配高写入、非结构化场景,减轻MySQL压力。

依赖引入

<!-- MongoDB 非结构化数据存储依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

配置与代码实现

spring:
  data:
    mongodb:
      uri: mongodb://127.0.0.1:27017/micro_log
@Service
public class LogMongoService {
    @Resource
    private MongoTemplate mongoTemplate;

    // 保存操作日志
    public void saveLog(OperateLog log){
        mongoTemplate.save(log);
    }

    // 条件查询日志
    public List<OperateLog> listLog(Long userId, String type){
        Query query = new Query();
        if(userId != null){
            query.addCriteria(Criteria.where("userId").is(userId));
        }
        if(StringUtils.isNotBlank(type)){
            query.addCriteria(Criteria.where("operateType").is(type));
        }
        return mongoTemplate.find(query, OperateLog.class);
    }
}

9.5 MySQL 主从读写分离

主库负责数据写入、更新、删除,从库负责所有查询,分担数据库压力,提升并发查询能力。

spring:
  shardingsphere:
    masterslave:
      load-balance-algorithm-name: round_robin  # 从库轮询查询
      master-data-source-name: ds0               # 主库
      slave-data-source-names: ds1              # 从库
    props:
      sql-show: true  # 打印SQL,方便调试

生产核心要点:1、分库分表禁止跨库联表、跨库事务;2、数据分层存储,各司其职,不混用存储组件;3、主从分离规避读写竞争,大幅提升数据库并发。

10 Flowable 工作流引擎落地

适配订单审批、财务报备、流程审核等各类审批场景,实现流程部署、发起、审批、驳回、查询全流程自动化,无需手动写流程状态机,标准化流程管理。

10.1 依赖引入

<!-- Flowable 工作流引擎依赖 -->
<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-spring-boot-starter</artifactId>
    <version>7.2.0</version>
</dependency>

10.2 核心流程操作实现

封装流程发起、审批、驳回通用方法,适配所有审批业务。

import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

@Service
public class FlowableService {
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;

    /**
     * 发起订单审批流程
     */
    public void startOrderFlow(String orderNo) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("orderNo", orderNo);
        variables.put("auditUser", "admin");
        // 根据流程定义Key发起流程
        runtimeService.startProcessInstanceByKey("order_audit_flow", orderNo, variables);
    }

    /**
     * 审批通过
     */
    public void auditPass(String taskId) {
        taskService.complete(taskId);
    }

    /**
     * 审批驳回
     */
    public void auditReject(String taskId, String reason) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("rejectReason", reason);
        taskService.complete(taskId, variables);
    }
}

生产核心要点:流程定义文件统一版本托管,禁止频繁动态修改;流程数据与业务数据双向联动,保证数据一致性。

11 权限认证体系(Sa-Token+Spring Security)

采用Sa-Token为主、Spring Security为辅的权限架构,Sa-Token轻量高效、开箱即用,适配绝大多数后台权限场景,简化传统Security繁琐配置;Spring Security辅助承接OAuth2第三方授权、单点登录能力,二者互补,实现登录认证、角色权限、接口拦截、账号封禁、会话管理全套能力,完全适配企业级权限体系。

11.1 核心依赖引入

<!-- Sa-Token 权限认证核心依赖 -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>satoken-spring-boot3-starter</artifactId>
    <version>1.37.0</version>
</dependency>

<!-- Spring Security 辅助授权依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

11.2 生产级Sa-Token配置

配置会话超时、Token有效期、拦截规则、跨域放行,适配微服务集群部署,支持多端登录、单点登录、账号踢出。

# Sa-Token 生产配置
sa-token:
  # token 名称(前端请求头携带参数)
  token-name: Authorization
  # token 有效期 2小时
  timeout: 7200
  # 临时有效期(无操作自动续期)
  activity-timeout: 1800
  # 关闭固定token,每次登录刷新token,提升安全性
  is-concat: false
  # 开启微服务无状态拦截
  is-read-cookie: false
  # 允许同一账号多端登录
  is-multi-login: true
  # 退出登录删除token
  is-logout-delete-token: true

11.3 全局权限拦截配置

统一配置接口白名单、权限拦截规则,无需每个接口单独注解,全局管控接口访问权限。

import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class SaTokenConfig implements WebMvcConfigurer {

    // 注册Sa-Token拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SaInterceptor(handler -> {
            // 放行所有白名单接口
            SaRouter.match("/system/login", "/system/register").stop();
            // 其余所有接口需要登录认证
            SaRouter.match("/**").check(r -> StpUtil.checkLogin());
        })).addPathPatterns("/**");
    }
}

11.4 登录、登出、权限校验实战

import cn.dev33.satoken.stp.StpUtil;
import org.springframework.stereotype.Service;

@Service
public class AuthService {

    // 账号密码登录
    public void login(String username, String password) {
        // 校验账号密码逻辑
        // ...
        // 登录成功,创建会话
        StpUtil.login(10001L);
        // 设置用户角色和权限
        StpUtil.getSession().set("role", "admin");
        StpUtil.getSession().set("permission", "system:order:*");
    }

    // 退出登录
    public void logout() {
        StpUtil.logout();
    }

    // 校验接口权限
    public void checkPermission() {
        // 校验是否拥有指定权限
        StpUtil.checkPermission("system:order:add");
        // 校验是否拥有指定角色
        StpUtil.checkRole("admin");
    }
}

生产核心要点:1、所有核心业务接口必须配置权限拦截,禁止匿名访问;2、敏感接口细化权限粒度,区分增删改查权限;3、支持在线踢出账号、强制下线、会话查询,适配后台用户管理。

12 JDK21 虚拟线程并发实战

JDK21 正式推出虚拟线程,彻底告别传统线程池线程数量受限、创建销毁开销大、上下文切换频繁的问题,轻量级、高并发、无需手动维护线程池,极大提升接口并发吞吐量,适配微服务高并发场景。

12.1 开启虚拟线程配置

SpringBoot3 原生支持虚拟线程,无需额外引入依赖,仅需配置开启全局虚拟线程调度。

# 全局开启虚拟线程
spring:
  threads:
    virtual:
      enabled: true

12.2 虚拟线程业务实战(高并发查询)

批量异步查询多业务数据,无需手动创建线程池,虚拟线程自动调度、自动回收,零开销。

import org.springframework.stereotype.Service;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

@Service
public class VirtualThreadService {

    // 虚拟线程批量并发查询业务
    public void batchQueryData() throws Exception {
        // 创建虚拟线程执行器
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            // 异步查询用户信息
            Future<Object> userFuture = executor.submit(this::getUserInfo);
            // 异步查询订单信息
            Future<Object> orderFuture = executor.submit(this::getOrderInfo);
            // 异步查询库存信息
            Future<Object> storageFuture = executor.submit(this::getStorageInfo);

            // 获取所有结果
            Object user = userFuture.get();
            Object order = orderFuture.get();
            Object storage = storageFuture.get();
        }
    }

    // 模拟用户查询
    private Object getUserInfo() { return null; }
    // 模拟订单查询
    private Object getOrderInfo() { return null; }
    // 模拟库存查询
    private Object getStorageInfo() { return null; }
}

生产核心要点:1、IO密集型业务(接口查询、数据库查询、MQ收发)优先使用虚拟线程,性能提升显著;2、CPU密集型业务不推荐使用虚拟线程;3、虚拟线程无需手动池化,框架自动管理,杜绝线程泄露。

13 OSS 大文件分片上传实现

针对大文件上传超时、传输失败、重复上传问题,基于阿里云OSS实现分片上传、断点续传、秒传、文件校验全套能力,适配图片、视频、压缩包等大文件上传场景,生产稳定可用。

13.1 核心依赖引入

<!-- 阿里云OSS文件上传依赖 -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.15.1</version>
</dependency>

13.2 OSS 基础配置

# 阿里云OSS配置
aliyun:
  oss:
    endpoint: oss-cn-beijing.aliyuncs.com
    access-key-id: your-key-id
    access-key-secret: your-key-secret
    bucket-name: micro-cloud-file

13.3 分片上传核心实现

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.List;

@Service
public class OssService {

    private OSS ossClient;

    // 初始化OSS客户端
    @PostConstruct
    public void initOss() {
        ossClient = new OSSClientBuilder()
                .build("oss-cn-beijing.aliyuncs.com", "your-key-id", "your-key-secret");
    }

    /**
     * 初始化分片上传
     */
    public String initMultipartUpload(String fileName) {
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest("micro-cloud-file", fileName);
        InitiateMultipartUploadResult result = ossClient.initiateMultipartUpload(request);
        // 返回分片上传唯一标识uploadId
        return result.getUploadId();
    }

    /**
     * 上传单个分片
     */
    public UploadPartResult uploadPart(MultipartFile file, String fileName, String uploadId, int partIndex) throws IOException {
        UploadPartRequest request = new UploadPartRequest()
                .setBucketName("micro-cloud-file")
                .setKey(fileName)
                .setUploadId(uploadId)
                .setPartNumber(partIndex)
                .setInputStream(file.getInputStream())
                .setPartSize(file.getSize());
        return ossClient.uploadPart(request);
    }

    /**
     * 合并所有分片,完成上传
     */
    public String completeUpload(String fileName, String uploadId, List<PartETag> partETags) {
        CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest(
                "micro-cloud-file", fileName, uploadId, partETags);
        CompleteMultipartUploadResult result = ossClient.completeMultipartUpload(request);
        // 返回文件完整访问地址
        return result.getLocation();
    }
}

生产核心要点:1、大文件统一采用分片上传,分片大小建议5MB;2、记录uploadId实现断点续传,避免重复上传;3、上传完成后校验文件MD5,防止文件损坏、篡改。

14 Docker+K8s 容器化部署

所有微服务统一容器化打包、部署、扩容,解决环境不一致、部署繁琐、扩容困难、版本混乱问题,实现一键打包、一键部署、弹性扩容、版本回滚,适配生产集群运维。

14.1 通用Dockerfile模板(所有微服务通用)

# 基础JDK21镜像
FROM openjdk:21-jdk-slim
# 设置工作目录
WORKDIR /app
# 复制打包后的jar包
COPY target/*.jar app.jar
# 开启时区统一
ENV TZ=Asia/Shanghai
# 暴露服务端口
EXPOSE 8080
# 启动命令
ENTRYPOINT ["java","-jar","/app/app.jar"]

14.2 K8s 部署核心配置

配置副本数、资源限制、健康探针、滚动更新策略,实现服务高可用、无损更新、自动重启恢复。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: micro-order
spec:
  # 启动3个副本,保证高可用
  replicas: 3
  selector:
    matchLabels:
      app: micro-order
  # 滚动更新策略,无损上线
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: micro-order
    spec:
      containers:
      - name: micro-order
        image: micro-cloud/order:1.0.0
        ports:
        - containerPort: 8080
        # 资源限制,防止服务抢占资源
        resources:
          requests:
            cpu: 100m
            memory: 256Mi
          limits:
            cpu: 500m
            memory: 512Mi
        # 存活探针,服务异常自动重启
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        # 就绪探针,启动完成后再接收流量
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

生产核心要点:1、所有服务至少部署2个副本,杜绝单点故障;2、严格配置资源限制,防止单服务占用全部集群资源;3、开启滚动更新,上线不中断业务。

15 Nginx 负载均衡与反向代理

统一入口转发、静态资源托管、负载均衡、跨域处理、限流拦截,承接前端所有请求,屏蔽后端服务地址,保护内网服务安全,分担网关压力。

15.1 生产级Nginx核心配置

# 全局配置
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    use epoll;
    worker_connections 65535;
}

http {
    # 开启gzip压缩,提升访问速度
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;

    # 后端微服务集群负载均衡
    upstream micro_gateway {
        server 127.0.0.1:8001 weight=3;
        server 127.0.0.1:8002 weight=3;
    }

    server {
        listen 80;
        server_name localhost;

        # 反向代理到网关
        location / {
            proxy_pass http://micro_gateway;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        # 限流配置,单IP每秒最多10次请求
        limit_req_zone $binary_remote_addr zone=all_req:10m rate=10r/s;
        limit_req zone=all_req burst=20 nodelay;
    }
}

生产核心要点:1、通过权重负载均衡实现流量分发;2、开启IP限流、防刷,拦截恶意高频请求;3、统一配置gzip压缩、超时时间,优化访问性能。

16 Jenkins+GitLab+K8s 全流程CI/CD

实现代码提交自动编译、自动打包、自动构建镜像、自动部署、自动回滚全流程自动化,彻底告别手动部署,提升迭代效率,规范上线流程。

16.1 Jenkins核心流水线配置

pipeline {
    agent any
    stages {
        stage('代码拉取') {
            steps {
                git url: 'http://gitlab.local/micro-cloud/micro-cloud-alibaba.git', branch: 'main'
            }
        }
        stage('代码编译') {
            steps {
                sh 'mvn clean package -Dmaven.test.skip=true'
            }
        }
        stage('镜像构建') {
            steps {
                sh 'docker build -t micro-cloud/order:${BUILD_NUMBER} .'
            }
        }
        stage('推送镜像') {
            steps {
                sh 'docker push micro-cloud/order:${BUILD_NUMBER}'
            }
        }
        stage('K8s部署更新') {
            steps {
                sh 'kubectl apply -f k8s-deploy.yaml'
            }
        }
    }
    // 构建失败告警
    post {
        failure {
            echo "服务部署失败,请及时排查问题"
        }
    }
}

生产核心要点:1、区分测试、预发、生产多环境流水线;2、版本号自增管理,方便版本追溯与回滚;3、跳过测试打包可根据场景调整,上线前必须执行单元测试。

17 核心缺失能力补齐(生产刚需)

严格按照需求剔除监控告警、高级架构能力,仅保留分布式核心能力、高频业务场景、性能优化、安全体系、参数校验规范刚需模块,补齐所有生产必备、项目缺失的核心功能,所有代码可直接复用上线。

17.1 分布式锁完整落地(Redisson)

解决高并发抢资源、库存超卖、并发修改数据问题,实现可重入锁、读写锁、自动续期、防死锁,适配所有并发业务场景。

依赖引入

<!-- Redisson 分布式锁核心依赖 -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.27.0</version>
</dependency>

生产级配置

# Redisson分布式锁配置
spring:
  redis:
    host: 127.0.0.1
    port: 6379
redisson:
  single-server-config:
    address: redis://127.0.0.1:6379
    database: 0
    # 锁默认等待时间
    lock-wait-time: 3000
    # 锁超时释放时间(看门狗自动续期)
    lock-lease-time: 30000

分布式锁实战代码

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service
public class DistributedLockService {
    @Resource
    private RedissonClient redissonClient;

    // 高并发库存扣减分布式锁
    public boolean deductGoodsStock(Long goodsId) {
        String lockKey = "lock:goods:" + goodsId;
        // 获取可重入锁
        RLock lock = redissonClient.getLock(lockKey);
        try {
            // 尝试加锁,等待3秒,持有锁30秒自动续期
            boolean tryLock = lock.tryLock(3, 30, TimeUnit.SECONDS);
            if (!tryLock) {
                return false;
            }
            // 执行业务逻辑:库存查询、扣减
            return true;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        } finally {
            // 释放锁
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}

17.2 全局接口幂等通用解决方案

解决表单重复提交、接口重复请求、MQ重复消费问题,实现接口幂等、表单防重、订单幂等通用方案,全局生效。

幂等工具类

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Component
public class IdempotentUtil {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    // 接口幂等校验:key为唯一请求标识(订单号、请求流水号)
    public boolean checkIdempotent(String key, long expireTime) {
        // 不存在则写入,请求放行;存在则拦截重复请求
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "1", expireTime, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(flag);
    }

    // 业务完成后删除幂等key(可选,根据场景适配)
    public void delIdempotentKey(String key) {
        redisTemplate.delete(key);
    }
}

接口防重实战

@RestController
@RequestMapping("/order")
public class OrderController {
    @Resource
    private IdempotentUtil idempotentUtil;
    @Resource
    private OrderService orderService;

    @PostMapping("/create")
    public String createOrder(@RequestParam String orderNo) {
        // 幂等校验:5秒内同一订单号禁止重复提交
        if (!idempotentUtil.checkIdempotent("order:idempotent:" + orderNo, 5)) {
            return "请勿重复提交订单";
        }
        return orderService.createOrder(orderNo);
    }
}

17.3 全局统一异常处理 + 统一返回体

规范项目所有接口返回格式、统一异常拦截、统一错误提示,杜绝前端返回格式混乱、报错信息暴露后端源码问题,生产必备基础能力。

统一全局返回结果封装

import lombok.Data;

@Data
public class Result<T> {
    // 响应码:200成功,500失败
    private Integer code;
    // 响应提示信息
    private String msg;
    // 响应数据
    private T data;

    // 成功返回
    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>();
        result.setCode(200);
        result.setMsg("操作成功");
        result.setData(data);
        return result;
    }

    // 失败返回
    public static <T> Result<T> fail(String msg) {
        Result<T> result = new Result<>();
        result.setCode(500);
        result.setMsg(msg);
        return result;
    }
}

全局统一异常处理器

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 全局未知异常拦截
    @ExceptionHandler(Exception.class)
    public Result<Void> handleException(Exception e) {
        e.printStackTrace();
        return Result.fail("系统异常,请稍后重试");
    }

    // 自定义业务异常拦截
    @ExceptionHandler(BizException.class)
    public Result<Void> handleBizException(BizException e) {
        return Result.fail(e.getMessage());
    }
}

17.4 数据脱敏通用实现

实现手机号、身份证、银行卡、邮箱自动脱敏,适配所有接口返回,无需手动处理,保护用户隐私数据。

public class DesensitizeUtil {

    // 手机号脱敏 138****1234
    public static String phone(String phone) {
        if (phone == null || phone.length() != 11) return phone;
        return phone.substring(0,3) + "****" + phone.substring(7);
    }

    // 身份证脱敏 110101********1234
    public static String idCard(String idCard) {
        if (idCard == null || idCard.length() < 18) return idCard;
        return idCard.substring(0,6) + "********" + idCard.substring(14);
    }

    // 邮箱脱敏 123****@qq.com
    public static String email(String email) {
        if (email == null || !email.contains("@")) return email;
        String[] split = email.split("@");
        return split[0].length() > 3 ? split[0].substring(0,3) + "****@" + split[1] : email;
    }
}

17.5 接口防刷、防重放安全方案

通过时间戳+随机数校验,拦截恶意重放请求、爬虫高频请求、恶意刷接口,保障接口安全。

// 自定义接口拦截器实现防重放、防刷
@Component
public class RequestSecurityInterceptor implements HandlerInterceptor {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    // 请求有效时间 5分钟
    private static final long REQUEST_VALID_TIME = 300000;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 获取请求参数:时间戳、随机数
        String timestamp = request.getHeader("timestamp");
        String nonce = request.getHeader("nonce");

        // 1、参数非空校验
        if (StringUtils.isBlank(timestamp) || StringUtils.isBlank(nonce)) {
            throw new BizException("非法请求");
        }

        // 2、校验请求是否过期
        long current = System.currentTimeMillis();
        if (current - Long.parseLong(timestamp) > REQUEST_VALID_TIME) {
            throw new BizException("请求已过期");
        }

        // 3、校验随机数是否已使用,防重放
        String key = "request:nonce:" + nonce;
        if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
            throw new BizException("禁止重复请求");
        }
        redisTemplate.opsForValue().set(key, "1", 5, TimeUnit.MINUTES);
        return true;
    }
}

17.6 全局参数校验统一规范实现(刚需)

基于JSR380规范实现全局参数校验、分组校验、统一异常处理,替代手动if判断参数,规范所有接口入参校验,代码极简、统一报错格式。

依赖引入

<!-- JSR380 参数校验核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

分组校验接口(适配新增、修改不同校验规则)

// 新增分组
public interface AddGroup {}

// 修改分组
public interface UpdateGroup {}

实体类参数校验注解使用

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;

@Data
public class OrderDTO {

    // 新增无需订单号,修改必须传订单号
    @NotNull(message = "订单号不能为空", groups = UpdateGroup.class)
    private String orderNo;

    // 新增、修改都必须传用户ID
    @NotNull(message = "用户ID不能为空", groups = {AddGroup.class, UpdateGroup.class})
    private Long userId;

    // 商品名称非空校验
    @NotBlank(message = "商品名称不能为空")
    private String goodsName;
}

接口开启参数校验

@RestController
@RequestMapping("/order")
public class OrderController {

    // 新增接口:适配新增分组校验
    @PostMapping("/add")
    public Result<Void> addOrder(@Validated(AddGroup.class) @RequestBody OrderDTO orderDTO) {
        // 无需手动校验参数,框架自动拦截
        return Result.success(null);
    }

    // 修改接口:适配修改分组校验
    @PostMapping("/update")
    public Result<Void> updateOrder(@Validated(UpdateGroup.class) @RequestBody OrderDTO orderDTO) {
        return Result.success(null);
    }
}

全局参数校验异常统一拦截

整合到全局异常处理器,统一参数报错格式,前端无需单独适配。

// 参数校验异常拦截
@ExceptionHandler(MethodArgumentValidationException.class)
public Result<Void> handleValidException(MethodArgumentValidationException e) {
    String message = e.getBindingResult().getFieldError().getDefaultMessage();
    return Result.fail(message);
}

生产核心要点:1、所有接口入参必须使用注解校验,禁止手写if判断;2、新增、修改场景使用分组校验,精细化控制校验规则;3、统一参数异常返回格式,前后端对接更规范。

17.7 定时任务XXL-Job完整落地

补齐分布式定时任务能力,实现定时任务新增、执行、重试、日志、分片执行,替代原生SpringTask,适配集群部署、防止任务重复执行。

依赖引入

<!-- XXL-Job 分布式定时任务依赖 -->
<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.4.0</version>
</dependency>

生产配置

# XXL-Job配置
xxl:
  job:
    admin:
      addresses: http://127.0.0.1:8088/xxl-job-admin
    executor:
      appname: micro-order-job
      port: 9999
      log-path: /data/xxl-job/logs
      log-retention-days: 7

任务执行器配置 + 任务实战

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class XxlJobConfig {
    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        XxlJobSpringExecutor executor = new XxlJobSpringExecutor();
        executor.setAdminAddresses("http://127.0.0.1:8088/xxl-job-admin");
        executor.setAppname("micro-order-job");
        executor.setPort(9999);
        return executor;
    }
}
// 定时任务业务实现
@Component
public class OrderJobHandler {

    // 定时关闭超时未支付订单
    @XxlJob("closeOverdueOrderJob")
    public void closeOverdueOrder() {
        // 执行定时任务逻辑:查询超时订单、关闭订单、释放库存
    }
}

18 项目总结与生产避坑指南

本手册基于Spring Cloud Alibaba 2023最新稳定生态,完整搭建企业级微服务架构,覆盖服务治理、分布式事务、消息解耦、缓存架构、数据存储、权限体系、容器部署、CI/CD自动化、生产刚需通用能力全套核心能力,剔除非刚需监控、高阶架构内容,聚焦项目落地、线上生产、面试高频场景。

18.1 核心技术亮点总结

  • 架构标准化:统一工程分层、依赖管理、代码规范,彻底解决项目混乱、难以维护问题;

  • 分布式问题全覆盖:分布式锁、幂等性、分布式事务、消息可靠消费,解决线上核心分布式难题;

  • 高并发性能优化:二级缓存、虚拟线程、读写分离、分库分表,全方位提升系统并发能力;

  • 生产安全规范:参数校验、数据脱敏、接口防刷、统一异常返回,规避线上安全与规范问题;

  • 自动化运维:容器化部署、CI/CD流水线,实现一键上线、弹性扩容、版本回滚。

18.2 线上生产高频避坑指南

  • 事务避坑:Seata大事务拆分、TCC严格实现幂等空回滚、写接口禁止Dubbo重试;

  • 缓存避坑:必须处理缓存穿透、击穿、雪崩,禁止缓存热点Key过期失效、禁止缓存大量无效数据;

  • 消息避坑:所有MQ消息必须幂等、失败重试、死信兜底,杜绝消息丢失、重复消费;

  • 并发避坑:高并发场景必须加分布式锁,禁止本地锁管控集群并发资源;

  • 参数避坑:所有接口入参统一校验,禁止空参数、非法参数流入业务逻辑;

  • 部署避坑:生产禁止单副本部署、禁止关闭健康探针、禁止手动修改线上配置。