
简介这是一套基于若依框架的Spring Cloud微服务前后端分离项目面向熟悉Spring Boot并希望上手微服务架构的后端开发者也适合需要快速搭建企业级权限管理系统的团队。项目整合了Nacos作为注册与配置中心、Sentinel实现流量控制与熔断降级、Seata处理分布式事务并结合Redis完成权限认证前端采用Vue3、Element Plus与Vite技术栈通过模块化设计降低业务耦合并提供完整的前后端联调示例。压缩包共677个文件以261个Java源码文件、89个Vue页面组件、75个JavaScript脚本为核心辅以XML与YAML配置文件、SQL初始化脚本、Dockerfile容器化配置以及多个启动批处理命令整体体积132.24MB目录结构清晰便于按模块查阅。已有3575人学习下载内容涵盖网关、认证、系统管理等多个微服务模块并提供了运行与打包脚本能快速启动整套环境。开发者可直接参考其服务拆分思路、配置中心与限流熔断的落地写法减少搭建成本并加速二次开发。 先交代一下背景我去年开始用“若依”做后台管理项目当时选型的是RuoYi-Cloud这个分支。整体技术栈就是标题里那套——SpringCloud Alibaba Nacos Sentinel Seata前端用的Vue3。折腾小半年从环境搭建到线上排障都摸了一遍。这篇就把整个拆解和踩坑记录沉淀下来给正准备上手或者已经在这条路上挣扎的朋友做个参考。1. 项目概述与架构选型思路1.1 为什么选若依微服务版而不是单体版市面上的后台管理系统若依算是知名度最高、资料最全的一个。不过大多数人起步用的都是单体版基于Spring Boot的那个分支而RuoYi-Cloud这种微服务版用得相对少一点很多人一看模块拆得稀碎就劝退了。我当时的场景比较特殊公司内部要做一套带多个业务域的系统除了用户、角色、菜单这些通用模块还要在同一个后台里挂不同业务的微服务彼此独立迭代、独立部署。单体版虽然上手快但到后期所有业务代码都堆在一个工程里光是依赖冲突、启动时间、发布协调就够受的。所以选RuoYi-Cloud这个分支是对的。不过要注意RuoYi-Cloud并不是从零教你写微服务的它的定位是一个微服务版的快速开发脚手架。也就是说网关、鉴权、认证、系统管理这些公共能力它已经给你搭好了你要做的是在这个基础上扩展自己的业务服务以及理解清楚这套基础设施是怎么协作的。1.2 一套微服务各自解决什么问题这套组合里每个组件都有明确的分工我用大白话梳理一下Nacos负责两件事一是服务注册与发现就是各个服务之间怎么找到对方二是配置中心所有服务的配置文件集中管理改配置不用重新打包重启。Sentinel负责流量防护包括限流控制单位时间内的请求量、熔断下游服务挂了上游快速失败而不是一直等着、系统负载保护。Seata负责分布式事务解决“一个操作跨多个服务、多个数据库要么全成功要么全失败”的问题。Vue3负责前端界面新项目直接用Vue3的组合式API比之前Vue2的选项式API写起来顺手得多。这样说可能还是有点抽象。举个例子用户订单支付订单服务要调扣库存服务再调账户余额服务。如果库存扣了、余额没扣成功钱货两清就出乱子了。Seata就是干这个的。如果某个服务突然响应特别慢比如数据库死锁了Sentinel就会把这个服务的调用熔断掉避免请求一直堆积导致整个系统崩溃。而Nacos则是所有服务能互相通信的基础离开了注册中心服务之间连地址都找不到。1.3 这套组合适合谁、怎么用如果你是以下情况这套方案很值得参考公司或项目需要从单体架构逐步演进到微服务架构需要一个现成的骨架而不是从零搭一套注册中心、网关、鉴权系统你的业务涉及多个服务之间的数据一致性要求需要分布式事务能力你的系统有突发流量“双11”也好、秒杀也好至少预先有这种预期需要做限流熔断你想学习SpringCloud Alibaba生态需要一个真实的、可运行的项目来做对照。那么这套技术栈适合的人群也就可以总结了有Java基础、熟悉Spring Boot、能看懂基本的前端Vue代码、对微服务有概念但是缺一个实际落地项目的人。如果连Spring Boot都没怎么用过建议还是从单体版入手先把基础打牢再挑战微服务。2. 环境搭建与核心组件集成详解2.1 Nacos的安装与配置要点很多人第一次部署Nacos会有点懵这里面有几个容易搞混的概念需要先理清。Nacos的核心功能是两大块注册中心和配置中心。这俩可以在同一个Nacos服务里启用也可以只启用其中一个。对于若依微服务版来说两者都用所以默认的启动方式即可。我用的Nacos版本是2.2.x下载服务端压缩包之后解压进入bin目录Windows下启动是startup.cmd -m standaloneLinux/macOS下启动是sh startup.sh -m standalone。-m standalone表示单机模式开发环境足够了。如果是生产环境Nacos官方推荐集群模式至少三台机器起步配置方法在官方文档里有这里先不展开。启动成功后浏览器访问localhost:8848/nacos默认账号密码是nacos/nacos注意新版本的Nacos首次启动可能要求修改默认密码这是正常的按提示操作即可。这里有一个很关键的点Nacos服务端启动完只是第一步你的SpringBoot服务还必须引入Nacos的注册发现和配置管理的依赖并且在yml里指定Nacos地址。很多人的服务启动报错“找不到服务”八成是Nacos客户端依赖没加全或者yml里的spring.cloud.nacos.discovery.server-addr配错了。2.2 微服务模块初始化从Gitee拉取RuoYi-Cloud开始从Gitee上拉取RuoYi-Cloud代码后你看到的是一个多模块Maven工程主要的模块有ruoyi-gatewaySpringCloud Gateway网关服务所有外部请求都先进网关再做路由转发ruoyi-auth认证服务负责登录、发放Tokenruoyi-system系统管理服务用户、角色、菜单、部门等核心管理功能ruoyi-job定时任务服务集成Quartzruoyi-file文件服务处理上传下载ruoyi-gen代码生成服务根据数据库表结构生成前后端CRUD代码ruoyi-common公共模块包括核心工具类、安全模块、日志模块等。初次导入Maven会下载大量依赖耐心等待就行。然后你需要做两件事一是导入根目录下的sql文件夹里的数据库脚本二是修改每个服务里bootstrap.yml中Nacos的地址。默认是localhost:8848如果你Nacos不在本机这里必须改。这里我要分享一个特别容易踩的坑RuoYi-Cloud的配置文件并不是全部写在项目里而是配置在Nacos配置中心。你执行startup.cmd -m standalone启动Nacos后要用浏览器打开Nacos控制台在配置管理-配置列表里逐个创建各个服务的配置文件。每个服务在bootstrap.yml中指定了自己要读取的dataId和group如果你Nacos里没有对应的配置这个服务启动时会直接报错提示找不到配置。这个问题我一开始就中招了以为配置都在项目里结果网关服务不断重启日志里有一句“dataId: ruoyi-gateway.yaml, group: DEFAULT_GROUP not found”。后来才明白RuoYi-Cloud官方把这套配置整理得非常清晰Nacos里的配置和项目的yml是对应的本地工程里只保留了bootstrap.yml作为启动引导其余的业务配置、公共配置都在Nacos上管理。2.3 Sentinel的接入方式与规则持久化Sentinel接入若依微服务版主要是靠依赖和配置。在ruoyi-common或你要保护的业务服务里引入spring-cloud-starter-alibaba-sentinel依赖然后在yml里配置Sentinel控制台地址和控制台端口。若依框架自带了Sentinel的依赖管理所以版本不用你操心。启动业务服务后打开Sentinel控制台默认端口8080就能看到服务已接入。控制台可以配置限流规则、熔断规则、系统规则配置后实时生效。但是有一个坑必须说默认情况下Sentinel规则保存在内存里服务一重启规则全部丢失。如果你只是本地玩玩那无所谓如果你是给公司做项目必须做规则持久化。持久化方案有几种比如推送到Nacos配置中心或通过Sentinel的DataSource接口对接数据库。我用的方案是Nacos持久化在Nacos配置中心创建限流规则配置文件然后在代码里通过PostConstruct初始化ReadableDataSource将Nacos中配置的规则自动加载到Sentinel。这样即使服务重启规则依然存在而且改规则时不需要重启服务通过Nacos的配置刷新能力Sentinel会感知到变化并更新规则。具体做法是在需要限流的服务里新建一个类实现ApplicationRunner或者PostConstruct初始化方法在这个方法里创建NacosDataSource并注册到FlowRuleManager。伪代码如下Configuration public class SentinelNacosDataSource { PostConstruct public void init() { String serverAddr 127.0.0.1:8848; String dataId sentinel-flow-rule; String group SENTINEL_GROUP; ReadableDataSourceString, ListFlowRule flowRuleDataSource new NacosDataSource(serverAddr, group, dataId, source - JSON.parseObject(source, new TypeReferenceListFlowRule() {})); FlowRuleManager.register2Property(flowRuleDataSource.getProperty()); } }然后在Nacos中创建对应的dataId和group的配置文件内容就是要限流的规则JSON数组。这样每次Nacos里的配置变更Sentinel都会自动更新做到了规则的动态化管理。2.4 Seata分布式事务集成AT模式与Seata-Server部署Seata在整个若依微服务版里接入难度比Nacos和Sentinel都高一些核心原因是Seata-ServerTC要先启动并且要往数据库里建几张表。先说Seata的两种经典模式AT模式和TCC模式。AT模式对业务代码侵入极小它自动解析SQL会在你执行增删改之前生成undo_log回滚日志如果后续步骤发生异常Seata会通过undo_log自动回滚之前的操作。若依微服务版里集成Seata推荐用AT模式因为对业务代码的干扰最小。具体步骤是部署Seata-ServerTC。去GitHub下载Seata服务端解压后修改conf/registry.conf文件将注册中心改为Nacos使得Seata-Server能注册到Nacos上被各个微服务找到。初始化Seata依赖的数据库表。Seata在AT模式下需要一张undo_log表每个业务数据库都要建这张表全局事务锁相关的表在Seata-Server的db目录下有初始脚本需要导入。在业务服务里引入spring-cloud-starter-alibaba-seata依赖并配置Seata相关参数主要是tx-service-group。然后在yml里指定seata.tx-service-group与Seata-Server的映射关系。在需要开启分布式事务的方法上加上GlobalTransactional注解。这个注解是全链路分布式事务的入口作用类似于本地事务的Transactional但控制范围是整个微服务调用链。我踩过的一个坑是Seata版本不兼容。RuoYi-Cloud的依赖里Seata版本和Seata-Server版本必须严格对应否则服务启动时TC注册不上事务回滚也不生效。建议直接用RuoYi-Cloud官方pom里的版本号去匹配不要自己瞎升级这也是若依微服务版本的一个通病——它锁定的依赖版本往往不是最新的但却是最稳的。2.5 Vue3前端工程结构解读RuoYi-Cloud的前端工程叫ruoyi-ui提供了Vue2和Vue3两个版本。大多数人用Vue2居多但我强烈建议直接上Vue3因为组合式API带来的代码复用能力比选项式API强不少而且Vue3的生态现在也成熟了。Vue3版本的若依前端整体目录结构和Vue2版本很像src/views下是各个页面src/api下是对应后端的接口调用。与后端对接时有一个很重要的配置点前端访问路径中带上了服务名。比如前端访问/prod-api/system/user/list网关需要根据/system这个前缀路由到ruoyi-system服务。这里要特别说明一下如何自定义新增一个前端页面并让它访问到你新建的微服务。首先你在Vue3工程里新建一个.vue文件然后在src/api下创建对应的JS文件axios请求的url写成/你的服务名/具体接口路径的形式。这样网关会自动转发到对应的微服务。我第一次用Vue3改造时踩了一个很有意思的坑Vue3删除了Vue.prototype.$xxx这种全局挂载方式若依框架原本很多组件用this.$modal、this.$auth等组件方法都是基于Vue2原型链扩展的。Vue3版本里官方改用mitt事件总线或者provide/inject来解决所以你在网上搜到的很多若依Vue2自定义扩展代码是不能直接迁移到Vue3的。前端接口调不通的时候建议先看一下浏览器F12控制台的完整报错信息。如果请求能到达网关通常会返回401或404有具体的错误码如果请求没到网关那就是前端代理配置有问题去看vue.config.js里的代理配置即可。3. 核心配置详解与参数选择3.1 Nacos命名空间、分组与多环境隔离策略Nacos里有几个概念理解透了配置管理就通了一半。命名空间Namespace用于彻底隔离数据同一个Nacos服务可以创建多个命名空间不同命名空间之间配置和服务是隔离的分组Group用于在同一命名空间内做更细粒度的区分。我在实际项目中是这样做的开发环境所有配置放在public命名空间默认下分组用DEFAULT_GROUP测试环境单独建一个命名空间test分组用TEST_GROUP甚至直接用命名空间隔离生产环境单独建命名空间prod并且关闭Nacos控制台的公网访问权限防止配置被误改或泄露。这样多环境管理非常清晰各服务通过bootstrap.yml中spring.cloud.nacos.config.namespace和group参数来指定自己该读哪份配置。3.2 Nacos配置动态刷新机制与常见误区Nacos配置中心的强大之处在于动态刷新修改Nacos中的配置服务不需要重启就能获取到最新值。实现动态刷新的方式是在类上标注RefreshScope注解。例如你有一个配置项custom: upload-path: /data/files在代码里这样使用Component RefreshScope public class UploadPathConfig { Value(${custom.upload-path}) private String uploadPath; public String getUploadPath() { return uploadPath; } }这样修改了Nacos中的配置值后这个Bean会被SpringCloud重新创建新的值自动注入。不过有几个误区必须澄清。不是所有配置都适合动态刷新比如数据源连接池的配置如果频繁改可能导致连接池重建RefreshScope也不是万能的它只能刷新自己作用域内的Bean。此外如果你用的是ConfigurationProperties那么需要确保这个配置类上有RefreshScope注解才能动态更新。3.3 Ruyi-Cloud的Token鉴权与网关过滤链若依微服务版的鉴权流程是这样的登录请求发到网关网关把请求路由到ruoyi-authruoyi-auth校验用户名密码成功后生成一个Token默认是JWT当然也可以改成Redis存储返回给前端。之后前端每次请求都带上这个Token网关有全局过滤器负责校验Token的合法性校验通过后才路由到目标服务。这个流程中有一个需要特别注意的地方网关校验Token时会调用Redis查询用户信息和权限信息。所以Redis挂了整个系统的请求都会失败。因此Redis的高可用非常重要生产环境至少要主从有条件就上集群或者哨兵模式。RuoYi-Cloud中白名单配置在Nacos的网关配置里具体是security.ignore.whites参数把不需要认证的URL加进去。比如登录接口、验证码接口、文件下载接口等。这个配置改了之后注意看是否需要重启网关部分版本修改后无需重启但个别版本行为不一致稳妥起见还是重启一次。3.4 Vue3环境变量与多环境打包Vue3前端工程里环境变量通常放在.env.development、.env.production、.env.test等文件里变量名为VITE_APP_BASE_API代表接口的基础路径。在开发环境这个变量通常是/dev-api然后通过vue.config.js里的代理转发到localhost:8080网关地址在生产环境这个变量通常直接写成/prod-api由Nginx把请求反向代理到网关。前端多环境打包这块我建议每次发布前依次检查这三件事.env.production里的VITE_APP_BASE_API是否为当前环境的正确值vue.config.js里的代理是否被Nginx配置覆盖生产环境一般不走开发代理而是Nginx转发打包产物dist里的js文件是否引用了正确的域名/端口。如果打包后接口返回404或者跨域报错90%是这几个位置的配置不对齐。4. 常见问题与排查技巧实录4.1 服务启动失败找不到Nacos配置症状启动ruoyi-gateway报错“dataId: ruoyi-gateway.yaml, group: DEFAULT_GROUP not found”。绝大多数原因就是Nacos配置中心里没有创建对应的配置。排查步骤打开Nacos控制台进入配置管理-配置列表看ruoyi-gateway.yaml、ruoyi-auth.yaml、ruoyi-system.yaml等文件是否都存在没有就手动创建或者更省事在RuoYi-Cloud的仓库中找sql目录或doc目录下的Nacos配置导出文件直接导入。如果是自定义的新服务需要在Nacos配置中心新建配置文件并在对应服务的bootstrap.yml里指定dataId和group这部分容易漏但很重要。4.2 Sentinel控制台看不到服务或规则不生效Sentinel控制台看不到服务先检查依赖有没有加到ruoyi-common的公共pom里或者这个服务是不是从来没被请求过——Sentinel的规则是懒加载的只有服务被实际调用后才会在控制台出现。这个点很迷惑人我第一次用的时候不停刷新控制台一直看不到后来查了文档才知道要先发一个请求。规则不生效首先要区分是规则没保存成功还是没加载成功。如果是保存在内存里重启后丢失这是正常的。如果是通过Nacos持久化重启后规则也没有那大概率是Nacos里配置的JSON格式写错了比如JSON数组的语法错误导致FlowRuleManager加载失败。此时打开Nacos配置看下有没有红色语法提示或者直接看服务启动日志中是否报解析异常。4.3 Seata分布式事务不生效Seata事务不生效先检查这几个地方按概率从高到低排Seata-Server有没有成功注册到Nacos打开Nacos服务列表看是否有名为serverAddr或类似的服务tx-service-group是否和Seata-Server端的配置对应上用错分组名是高频问题所有参与分布式事务的服务是否都正确引入了Seata依赖并配置了registry.conf里的Nacos地址数据库是否建了undo_log表这张表缺失AT模式回滚会直接失败。发起全局事务的方法是否加上了GlobalTransactional而不是Transactional前者是Seata管理的后者只是本地数据库事务。还有一个隐蔽的坑如果两个服务之间通过Feign调用Feign接口所在的包路径没有被启动类扫描到调用会失败事务自然也就无法保证。这种情况排查起来很费劲因为表面看是404或500报错实际根源在于Feign接口没有被注册成Bean。4.4 若依框架开发过程中常见例外规则若依微服务版由于模块多开发过程中会遇到一些框架自身的限制。比如代码生成器生成的代码默认是针对于单体版或单服务版的如果你要用代码生成器直接生成微服务模块需要手动修改生成的代码路径和包名然后复制到对应的服务模块下。这项工作比较机械但没办法完全自动化我通常能自己做就自己做除非业务量大才考虑写自动化脚本。另外要注意的是若依自带的权限注解PreAuthorize在微服务下是正常的但是如果你需要跨服务鉴权比如服务A要校验用户是否有某个权限那么需要在网关把用户的权限信息传递下去。若依的做法是在网关校验后把用户信息放入请求头服务端从请求头里解析。自定义服务要继承这个逻辑否则会出现前端调通了实际上权限校验却一直不通过的现象。4.5 性能调优一点经验微服务部署时JVM参数和线程池参数建议显式指定。网关服务的线程池默认值一般满足不了高并发场景建议根据压测结果适当调大spring.cloud.gateway.thread-pool相关的参数同时给JVM设置合理的初始堆和最大堆大小。Sentinel的熔断配置也有讲究。不要只设置限流而忽略了熔断因为限流是尽最大努力保护自己但熔断是在下游已经出问题时快速失败两者结合才能达到保护效果。通常我会设置熔断策略慢调用比例或异常比例比如异常比例超过20%时触发熔断熔断窗口10秒左右熔断后不立即放行而是等窗口结束再尝试最小请求数在窗口内至少需要多少个请求才进行熔断判断防止偶发异常导致熔断误触发。这些参数不是越大越好也不是越小越好要看具体业务。比如秒杀场景限流QPS可以设置的比较高比如1000以上普通后台管理系统的QPS可能几十就差不多了。熔断的异常比例阈值对核心链路建议严格一点对非核心链路可以放松防止一个非核心服务的抖动把主流程拖垮。5. 部署发布与运维监控建议5.1 微服务的打包与镜像构建RuoYi-Cloud每个微服务都是一个可独立运行的jar包。打包命令在根目录执行mvn clean package -Dmaven.test.skiptrue然后各模块的target目录下会生成对应的jar包。生产环境部署我建议把每个微服务都做成Docker镜像用Docker Compose或Kubernetes编排。我这里用的最多的还是Docker Compose方式机器少、场景固定够用且维护成本低。针对每个服务写一个Dockerfile大致内容如下FROM openjdk:17-jdk-slim MAINTAINER yourname RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime RUN echo Asia/Shanghai /etc/timezone COPY ruoyi-gateway.jar /app/ruoyi-gateway.jar ENV JAVA_OPTS-Xms512m -Xmx512m -Dfile.encodingutf-8 ENTRYPOINT [sh, -c, java $JAVA_OPTS -jar /app/ruoyi-gateway.jar]镜像可以打到私有仓库生产服务器拉取运行。这里有一个经验如果服务器内存有限不要每个服务都分配512M以上堆内存。Nacos、Seata-Server这些基础设施本身也要占用不小的内存加上业务服务经常会遇到内存不足。建议给每个Java服务按照业务重要程度分配内存网关等核心入口给充足的内存非核心任务服务可以适当调小。5.2 日志收集与链路追踪微服务排障最大的痛点就是日志分散在各处。我用了最简单的方案所有服务把日志输出到JSON文件再用Filebeat采集到ElasticsearchKibana里统一查看。这个方法在中小团队里非常实用而且完全开源。如果条件允许建议接入SkyWalking或者Zipkin做链路追踪。微服务一次请求可能跨好几个服务如果每个服务都自己打日志排一次trace要手工对时间戳和orderId效率非常低。SkyWalking这类工具能把一次请求的完整调用链展示出来哪个环节慢一目了然。RuoYi-Cloud本身没有集成链路追踪组件但可以基于SkyWalking的agent方式无侵入接入对所有微服务生效。具体做法是下载SkyWalking的agent目录在每个服务的启动脚本中加上-javaagent:/path/to/skywalking-agent.jar然后在配置文件中指定SkyWalking后端地址。这个方案对接若依微服务版非常丝滑不需要改任何业务代码。5.3 数据库层面的考虑微服务化后每个微服务应该有自己的独立数据库这是微服务落地的一个原则。但若依在这一点上做得比较“友好”——它默认所有服务都连同一个数据库降低初学门槛。实际项目中如果你拆分了独立的服务建议也把数据库拆开避免服务之间互相干扰。拆库之后跨库查询无法用SQL直接做了一般通过以下方案解决在服务层聚合数据比如用户服务提供接口订单服务通过Feign调用用户服务获取用户名之类的字段引入缓存把常用数据冗余一份到本服务的缓存里减少跨服务调用频率更重型的方案是引入Canal监听MySQL的binlog同步数据但这对中小项目来说有点过度设计了。如果不想拆库那就要接受一个事实全局事务的复杂度会飙升。Seata能解决分布式事务但是跨多个数据库、多个服务的调用链一旦变长性能损耗也比较明显。我实际运行下来的感受是非关键链路能不用分布式事务就不用优先通过重试、补偿、对账等最终一致性方案来处理性能比强一致好得多代价是要接受短时间内数据不一致。6. 个人实操心得与扩展建议我实际的感受是若依SpringCloud版这套技术栈在整个Java微服务生态里已经算是一套相当成熟的组合方案。Nacos做注册和配置Sentinel做流量防护Seata做分布式事务每个组件都是阿里开源的明星产品社区活跃度和资料丰富度都有保障。对个人成长和公司项目来说这套技术栈的学习成本低、收益高尤其是你把这套东西吃透之后再去看其他微服务项目会发现很多套路都是通用的。最后再分享一个我踩了很多次坑才领悟的细节若依微服务版本地调试时不要开着Nacos的权限认证来调试。Nacos从2.2.1版本开始默认开启了用户登录认证如果你配置了复杂的用户权限网关、配置读取这些都会报401。本地开发调试时可以先把认证关闭在Nacos的application.properties里改配置等到联调和生产环境再开启。这个细节不算难但能给你省下大量排查时间。内容先写到这里。这套东西我自己从搭环境、写代码、部署上线全程走了一遍深知里面的坑和成就感。如果你正在这条路上遇到具体问题欢迎留言交流我尽量知无不言。本文还有配套的精品资源点击获取