简介:若依SpringCloud微服务版本是一套前后端分离的企业级开发脚手架,整合Spring Boot、Spring Cloud Alibaba、Nacos注册与配置中心、Sentinel限流熔断、Seata分布式事务及Redis权限认证,前端基于Vue3、Element Plus与Vite,适合需要快速搭建微服务架构的Java全栈开发者。压缩包共677个文件,以java源码、vue页面、xml与sql配置为主,辅以yml、dockerfile环境定义以及bat、sh启动打包脚本,覆盖后端服务、前端工程、数据库脚本和集群部署等多个维度,整体体积132.24MB。已有3578人学习浏览,是一份经过验证的微服务落地参考。通过这套工程,读者可以获得完整的若依Cloud前后端项目源码、Nacos/Sentinel/Seata集成的具体配置与启动顺序说明,以及可修改的容器化部署文件,能有效降低搭建高可用微服务环境的门槛,便于深入理解注册发现、配置管理、限流熔断和分布式事务等核心技术。
1. 微服务版若依的环境坑:不是框架难,是四个中间件先卡人
若依的 Spring Cloud 版几乎成了后端开发者接触微服务的第一套完整项目源码:Spring Cloud 全家桶、Nacos 做注册中心和配置中心、Sentinel 管限流熔断、Seata 管分布式事务,前端再配 Vue3。框架本身的代码不难读懂,真正让大多数人在把源码下载下来之后耗掉一个周末的,是这套依赖链的上手顺序——Nacos 连不上数据库导致配置拉取失败、Seata 事务分组对不上导致全局事务失效、Sentinel 启动后一直看不到服务、前端 npm 依赖装到一半直接报错,每一条都足以让整套微服务环境卡死在启动阶段。这篇文章按我实际搭这套环境的顺序写,从版本选型、Nacos 搭建、Seata 和 Sentinel 接入,一直写到常见问题排查和最终的跑通验证。适合刚把源码拿到手、正卡在“下一步到底先装什么”的开发者,也适合已经在这套环境上翻过车、想回头把配置细节对齐一遍的人。
2. 版本选型先于安装:JDK 8 配 MySQL 8,pom.xml 才是真正的版本表
2.1 别急着下载中间件,先把 pom.xml 里的 Spring Boot 分支看清楚
大多数若依微服务部署翻车的第一个原因不是命令敲错,而是装环境之前没有对齐版本。拿到源码后,第一步不是去下载 Nacos,而是打开根目录的pom.xml,看两样东西:Spring Boot 版本和 Spring Cloud Alibaba 版本。这个文件里锁定的版本号,决定了你本机要装的 JDK、Nacos、Seata、Sentinel 分别该用哪个大版本。
<properties> <java.version>1.8</java.version> <spring-boot.version>2.x.x</spring-boot.version> <spring-cloud.version>2021.0.x</spring-cloud.version> <spring-cloud-alibaba.version>2021.0.x.0</spring-cloud-alibaba.version> </properties>逻辑说明:Spring Boot 2.x 对应 JDK 8,Spring Cloud 2021.x 对 JDK 8 完全友好,不要看到网上说“新项目直接上 JDK 17”就跟着升。若依的分支里有明确标注 JDK 8 的,直接用 JDK 8 最稳。而spring-cloud-alibaba的版本号决定了 Nacos 客户端、Sentinel 客户端和 Seata 客户端的默认行为,这几个组件在客户端的实现是相互配套的,单独把某一个中间件的版本升得很高,反而会让客户端序列化方式和服务端对不上。
我一般会建议:把 pom.xml 里这几个 version 抄到记事本上,再对照中间件下载页面选版本。Nacos 2.x 对应 Spring Cloud Alibaba 2021.x,Seata 选 1.5 以上,Sentinel 控制台选 1.8.x。这套组合是当前若依微服务版最常见也最不容易出问题的搭配。参数没必要背,以你源码里实际锁定的版本为准。
2.2 JDK 8 安装与环境变量:避开系统里“两个 java”的黑匣子
JDK 装起来很简单,麻烦的是装完之后JAVA_HOME和PATH里解析出来的 java 不是同一个。很多服务器上自带的 OpenJDK 版本和项目要求的不一致,导致启动 Nacos 时报UnsupportedClassVersionError,看报错根本想不到是 JDK 路径指错了。
# Debian / Ubuntu 系 sudo apt install openjdk-8-jdk -y # CentOS / RHEL 系 sudo yum install java-1.8.0-openjdk-devel -y java -version echo $JAVA_HOME参数说明:装完先执行java -version确认版本是 1.8,再看JAVA_HOME是否为空。如果为空,要在/etc/profile或~/.bashrc里补上:
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk export PATH=$JAVA_HOME/bin:$PATH注意,export之后要source ~/.bashrc再重新打开终端。判断JAVA_HOME是否写对的最快方式,是执行readlink -f $(which java),把得到的真实路径和JAVA_HOME对比。多数人环境变量配置出错,就是JAVA_HOME写成了软链接路径,而实际 java 在另一个目录。曾经有台机器明明java -version显示 1.8,启动 Seata 却报缺少模块,排查到最后发现是/usr/bin/java被另一个高版本 JDK 的软链接劫持了,这类问题用readlink -f一眼就能看穿。
2.3 MySQL:5.7 还是 8.0,取决于你的建库脚本和 JDBC URL
若依微服务版的数据库脚本会提供ry-cloud、ry-config、ry-seata三个库的建表脚本。你需要手动先建库再导表,建库字符集统一用utf8mb4,否则后面微服务写入中文数据很容易出现乱码或者索引长度超限报错。
CREATE DATABASE `ry-cloud` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE DATABASE `ry-config` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE DATABASE `ry-seata` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;MySQL 5.7 和 8.0 我都在这套环境上跑通过。5.7 胜在兼容省心,8.0 需要注意 JDBC URL 的认证参数。如果你用的是 MySQL 8.0,后面微服务启动时很可能报Public Key Retrieval is not allowed,原因是 MySQL 8.0 默认使用caching_sha2_password认证,JDBC 驱动在非 SSL 连接下默认不允许自动获取公钥。解决办法是在每个微服务数据源 URL 末尾追加参数,这个后面排错章节会再展开。
Redis 在这套环境里用默认的 6379 端口装好即可,密码先不配置。若依后端从bootstrap.yml里读 Redis 地址,保持最简配置,等整套环境跑通之后再考虑加密码和做生产加固,这样可以少一个排错变量。
2.4 前端 Vue3 要的是 Node 16,不是最新的 Node 20
前端模块虽然是 Vue3,但对 Node 版本的宽容度没有想象中高。按我装过的经验,若依前面对 Node 16 最友好,Node 18 以上开始碰运气,Node 20 在 npm install 阶段大概率会遇到 sass 相关依赖编译失败。判断方法很简单:打开前端目录下的package.json,看engines字段有没有限定;没写就用 Node 16,绝不盲目追新。
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt install -y nodejs node -v npm config set registry https://registry.npmmirror.com npm -v参数说明:把 npm 镜像切到国内镜像,目的是让依赖下载阶段少等几分钟。如果你在公司内网已经有私有 npm 源,把 registry 换成内网地址即可,原理一样。版本对照关系可以整理成下面这样,方便装之前先对一遍:
| 环境组件 | 推荐版本 | 备注 |
|---|---|---|
| JDK | 1.8 | 以根 pom.xml 锁定为准 |
| MySQL | 5.7 或 8.0 | 8.0 需处理认证插件参数 |
| Redis | 默认 6379 端口 | 先不加密码,验证通过再加 |
| Nacos | 2.x | 与 Spring Cloud Alibaba 版本配套 |
| Seata | 1.5 以上 | 客户端与服务端版本保持一致 |
| Sentinel 控制台 | 1.8.x | Spring Boot 2.x 环境兼容性更好 |
| Node.js | 16.x | npm install 成功率最高的版本 |
3. Nacos 注册与配置中心:单机启动也必须做 MySQL 持久化
3.1 为什么 Nacos 不能直接用内嵌数据库跑
Nacos 默认支持用内嵌的 Derby 数据库以单机模式启动,很多新手被“快速开始”文档误导,直接startup.sh起来就以为装完了。但若依微服务的大量配置是存在 Nacos 配置中心的,gateway、auth、system 这些模块的 yml 配置全部靠它下发。一旦重启 Nacos,内嵌库数据状态异常,配置丢了之后所有微服务启动时拉不到配置,报的错五花八门,最典型的是configurations cannot be found和dataId not found。
把 Nacos 持久化切到 MySQL 是标准做法,也是这套环境必须做的第一步。先把 Nacos 自带的建表脚本导入到ry-config库:
mysql -uroot -p ry-config < nacos/conf/nacos-mysql.sql然后修改 Nacos 的application.properties:
spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://127.0.0.1:3306/ry-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai db.user.0=root db.password.0=你的数据库密码参数说明:db.num=1表示单数据源,db.url.0里的ry-config必须和前面建的库名完全一致。useSSL=false是避免本地连接 MySQL 时 SSL 握手报错,serverTimezone=Asia/Shanghai主要是防止 MySQL 8 的时区问题导致启动失败。改完再启动 Nacos,配置数据才会真正落到 MySQL 表里,这时候就算 Nacos 重启,配置也不会丢。
3.2 单机启动 Nacos:Windows 和 Linux 的启动参数不一样
# Linux / macOS 单机模式启动 sh startup.sh -m standalone # Windows 命令行启动 startup.cmd -m standalone-m standalone是单机模式参数,必须显式指定。不加这个参数时 Nacos 会按集群模式启动,在单机上会报成员节点相关的错误。Windows 用户最容易踩的坑是直接双击startup.cmd,弹窗一闪而过,以为装好了,其实进程根本没起来。我一般建议在 cmd 里执行,并且注意看输出的日志路径,启动失败时日志里会有明确原因。
Nacos 启动后访问http://localhost:8848/nacos,默认账号密码都是nacos/nacos,登录后第一件事是修改默认密码。Nacos 2.x 在未配置鉴权的情况下会持续输出安全提醒,单机开发环境可以先忽略,但如果你是把这套环境部署到服务器上暴露到公网的,必须配置nacos.core.auth.plugin.nacos.token.secret.key,否则控制台相当于裸奔。
3.3 把若依微服务配置导入 Nacos
若依源码目录里会带一套 Nacos 配置文件夹,里面是各微服务模块的 yml 配置。登录 Nacos 控制台,进入“配置管理-配置列表”,点“导入”按钮,选中解压后的配置目录,命名空间保持默认 public,分组保持DEFAULT_GROUP,直接导入。
导入后重点核对下面几个配置是否存在:
ruoyi-gateway-dev.ymlruoyi-auth-dev.ymlruoyi-system-dev.ymlruoyi-job-dev.ymlruoyi-common-dev.yml
ruoyi-common这类公共配置会被其他模块通过shared-configs共享,如果导入后微服务启动仍然报找不到配置,八成是 group 或 namespace 没对。若依默认不创建新命名空间,所有配置都在 public 和DEFAULT_GROUP下。还有一个细节:导入配置之前,先看一眼配置文件里的数据库连接、Redis 地址是不是本机的,如果不是,改完再发布,否则后面微服务启动时连的还是配置文件里的老地址。
3.4 后端微服务的 bootstrap.yml 要指向本地 Nacos
每个后端微服务模块的src/main/resources下都有bootstrap.yml,里面配置了 Nacos 连接信息。以 gateway 为例,通常长这样:
spring: application: name: ruoyi-gateway cloud: nacos: server-addr: 127.0.0.1:8848 config: file-extension: yml namespace: group: DEFAULT_GROUP shared-configs: ->registry { type = "nacos" nacos { application = "seata-server" serverAddr = "127.0.0.1:8848" group = "DEFAULT_GROUP" namespace = "" username = "nacos" password = "nacos" } } config { type = "nacos" nacos { serverAddr = "127.0.0.1:8848" group = "SEATA_GROUP" namespace = "" username = "nacos" password = "nacos" } }注意config段的 group 是SEATA_GROUP,这一步我经常看到有人和 registry 的 group 写成一样,结果 Seata 全局配置推送到 Nacos 后客户端读取时找不到。用脚本把 Seata 配置推送到 Nacos 时,脚本里指定的 group 必须和这里的config.nacos.group保持一致。改完配置启动服务端:
sh seata-server.sh -p 8091 -h 127.0.0.1参数说明:-p是 Seata 服务端口,默认 8091;-h是注册到 Nacos 的 IP。多网卡服务器上如果-h不显式指定,Seata 可能注册错 IP,客户端连接时一直超时。启动完成后先去 Nacos 控制台的“服务管理-服务列表”里确认有没有出现seata-server这个服务,出现才说明注册成功。
4.2 事务分组 vgroupMapping:客户端和服务端必须同名的关键
Seata 最容易出问题的点是“事务分组不一致”。客户端每个微服务通过tx-service-group定义逻辑事务分组,再通过vgroup-mapping把逻辑分组映射到 Seata 集群名;服务端也有同样的映射配置,两边的分组名必须一致。若依微服务模块里,Seata 配置通常在 Nacos 的common-dev.yml里,以某个业务服务为例:
seata: enabled: true application-id: ruoyi-system tx-service-group: my_test_tx_group registry: type: nacos nacos: server-addr: 127.0.0.1:8848 group: DEFAULT_GROUP config: type: nacos nacos: server-addr: 127.0.0.1:8848 group: SEATA_GROUP service: vgroup-mapping: my_test_tx_group: default参数说明:tx-service-group是逻辑分组名,vgroup-mapping下面的 key 必须和它一致,valuedefault是 Seata 集群名。服务端registry.conf里注册的应用名是seata-server,而default这个值与 Nacos 上 Seata 服务注册名之间还有一层映射,具体要看 Seata 版本的默认规则。新手阶段最常见的报错是Could not found global transaction xid和no available service,基本都是这个映射链路上某个名字对不上。我的建议是把tx-service-group固定写成my_test_tx_group,然后只在vgroup-mapping里调整 value,不要去动客户端和服务端各自身份定义。
4.3 Sentinel 控制台:jar 包启动,懒加载导致“看不到服务”
Sentinel 负责限流和熔断,若依每个微服务作为 Sentinel 客户端接入,需要先启动控制台。从源码对应的版本说明里找到 Sentinel Dashboard 的 jar 包,启动命令是:
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 \ -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar说明:控制台默认端口 8080,登录账号密码都是sentinel/sentinel。每个微服务要在 Nacos 的配置里加上 Sentinel transport 配置:
spring: cloud: sentinel: transport: dashboard: 127.0.0.1:8080 port: 8719参数说明:dashboard是控制台地址,port是微服务本机与 Sentinel 控制台通信的端口,默认 8719。注意这个端口会被客户端动态占用,如果 8719 被占,客户端会尝试 8720、8721 等递增端口,所以服务器防火墙里要放行 8080 和 8719 附近一段端口。
控制台刚打开时看不到业务服务是正常现象,Sentinel 是懒加载模式,服务第一次被调用后才会出现在控制台列表里。因此配置完不要干等,去请求几个真实接口,再刷新控制台看实时监控。很多人在这一步误以为配置错了,反复重启服务,其实是没触发流量。
4.4 限流和熔断规则:先落在控制台,验证通过再考虑持久化
Sentinel 的规则默认存在内存里,控制台重启规则就没了。若依的业务接口需要限流时,我一般先在控制台上针对具体服务新增“流控规则”,验证接口被拦截并返回兜底逻辑后,再考虑把规则持久化到 Nacos。持久化的方案在若依源码里有现成的配置类可以参考,但新手阶段不要一开始就折腾规则持久化,先把控制台能管理规则这条链路跑通,理解规则生效的逻辑,后面再优化也不迟。
5. 常见问题与排查:四条启动期的典型踩坑记录
5.1 现象:Seata 报 no available service / Could not found global transaction xid
原因:事务分组和 Seata 服务端注册信息对不上。常见的有两种,一是客户端tx-service-group与服务端映射不一致,二是seata-server启动时-h没指定 IP,注册到了127.0.0.1,而客户端与 Seata 不在同一台机器上,连不上 TC。
解决:先去 Nacos 控制台服务列表查看是否有seata-server,看注册的 IP 是不是服务器实际内网 IP。如果错成127.0.0.1,重启 Seata 时用-h指定内网 IP;同时对齐三个地方:registry.conf里 registry 的 group、config 的 group、客户端service.vgroup-mapping的 key。这三个只要有一个不一致,全局事务就会在分支注册阶段失败。排查时看业务服务日志里的 Seata 相关输出,通常能定位到是 registry 还是 config 段的问题。
5.2 现象:Sentinel 控制台启动成功,但服务列表一直为空
原因:一是 Sentinel 客户端懒加载,服务没有被调用过就不会注册;二是 8719 端口被占用后客户端尝试往上递增端口,防火墙没放行导致通信失败;三是bootstrap.yml里只配了dashboard地址,但transport.port没写或写错,客户端上报心跳失败。
解决:先telnet 127.0.0.1 8719确认端口通不通,再给需要限流的入口接口多发起几次 HTTP 请求,触发调用链,最后刷新控制台。如果还是看不到,去客户端日志里搜sentinel关键字,看有没有dashboard connect失败的记录。不要反复重启服务,Sentinel 的注册机制决定了它必须靠真实流量触发。
5.3 现象:npm install 装到一半报 node-sass / sass 版本不匹配
原因:Node 版本与前端依赖编译要求不一致。若依 Vue3 版前端如果依赖锁文件里带了 node-sass,Node 20 环境下编译大概率直接失败,报错信息里会出现gyp或者python相关字样,很容易误导人去装 Python,其实根本不是缺 Python,是 Node 版本太新。
解决:切换 Node 版本到 16.x,删除node_modules和package-lock.json,重新npm install。如果项目已经改用 Dart Sass,Node 18 可能能过,但保守起见还是按第 2 章的版本对照表来。切换 Node 版本推荐用版本管理工具,比反复卸载重装省时间;装完先node -v确认版本再进前端目录装依赖。这个坑是四个踩坑记录里最不值得花时间的——版本一对,一分钟解决。
5.4 现象:后端微服务启动报 Public Key Retrieval is not allowed
原因:MySQL 8.0 默认使用caching_sha2_password认证插件,JDBC 驱动在非 SSL 连接下默认不允许自动获取公钥,导致数据库连接建立失败。这个问题在 MySQL 5.7 上不会出现,所以很多人换库版本之后才发现。
解决:在 Nacos 配置中心的每个数据源 URL 末尾追加allowPublicKeyRetrieval=true&useSSL=false。比如:
url: jdbc:mysql://127.0.0.1:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true参数说明:allowPublicKeyRetrieval=true允许客户端向服务端获取公钥,useSSL=false跳过 SSL 握手,两个参数必须同时存在。改完配置去 Nacos 控制台发布,再重启相关微服务,不需要动本地代码。如果你用的是 MySQL 5.7,加不加这两个参数都不影响连接,但保留也无害。
6. 跑通验证:后端启动顺序、Nacos 服务列表和一笔分布式事务
6.1 服务启动顺序与检查点
这套环境的启动顺序有讲究,不能想到哪个起哪个。按下面这个顺序走,每一步都在上一步验证完成后再继续:
- MySQL、Redis 已就绪,三个库的脚本已导入。
- Nacos 已启动,种子配置已导入,控制台可登录。
- Seata 服务端已启动,Nacos 服务列表出现
seata-server。 - Sentinel 控制台已启动,8080 端口可访问。
- 后端按依赖顺序启动:
ruoyi-gateway→ruoyi-auth→ruoyi-system等业务模块。
后端服务全部启动后,去 Nacos 服务列表看每个服务名是否都变为 healthy。也可以用命令验证:
curl -X GET "http://127.0.0.1:8848/nacos/v1/ns/service/list?pageNo=1&pageSize=100&groupName=DEFAULT_GROUP"这个接口返回的是服务名列表,能列出ruoyi-gateway、ruoyi-auth、ruoyi-system等名字,说明注册成功。如果某个服务缺失,去对应的启动日志里找 Nacos 注册相关报错,不要盲目重启。
6.2 前端 Vue3 登录验证
cd ruoyi-ui npm install npm run dev参数说明:前端开发模式默认监听 80 端口,如果被占用,改前端根目录下vite.config.js里的server.port换一个端口。启动后打开浏览器访问登录页,输入默认账号admin / admin123,能出现验证码就说明网关、认证、系统三个服务的链路已经通了。
这一步很关键:登录页本身是静态页面,能打开不代表后端通;但验证码图片能加载出来,说明请求已经通过 Spring Cloud 网关走到了后端的/captchaImage接口。如果验证码一直转圈加载不出来,优先检查网关日志和后端服务的健康状态。登录成功后能进入首页看到菜单列表,整个 Spring Cloud 后端链路就算完全跑通了。
6.3 验证分布式事务:用测试接口查日志里的 XID
若依微服务版自带一个分布式事务测试入口,通常是模拟下单加扣库存的跨服务写操作。验证思路不是看页面,而是看日志里的 XID:
- 在前端菜单里找到分布式事务测试页面,触发一次模拟业务。
- 去参与事务的两个微服务日志里搜
xid,确认 TM 生成的全局事务 ID 被 RM 分支事务接收。 - 再触发一次测试,但这次让第二个服务内的逻辑人为制造异常,观察两个库的数据是否同时回滚。
Seata 的全局事务提交或回滚状态,可以通过日志里的global transaction关键字来确认。如果两个库一个提交一个没提交,说明事务分组没对齐或者分支事务注册失败,回到第 5.1 节排查映射关系。最直观的验证方式是直接查两个业务表的数据最终状态,比看页面成功提示更可靠。
从那以后,我每次拿到一套新的微服务源码,都强制先打开根pom.xml和前端package.json,把版本对上再动中间件;装完 Nacos、Seata、Sentinel 三个组件之后,不急着启动业务服务,先把服务列表和配置列表逐项核对一遍再继续。这套验证顺序看起来慢,实际能省下一个晚上排错的时间。希望这次的安装记录对你接下来的部署也能少踩几个坑,顺利把这套若依微服务环境跑通。
本文还有配套的精品资源,点击获取