大数跨境

7天学会SpringBoot+Vue3企业级项目RuoyiOffice(七):上线篇——从测试验收到部署上线,完成企业项目交付

7天学会SpringBoot+Vue3企业级项目RuoyiOffice(七):上线篇——从测试验收到部署上线,完成企业项目交付 企业软件源码
2026-10-07
13
导读:把前六天做出来的 OA 用车申请放到生产环境:分清 dev、demo、prod 三套配置,完成后端打包、前端构建、Nginx 反代、HTTPS 与 WebSocket,管好密钥、日志与备份,最后给出上

7天学会SpringBoot+Vue3企业级项目RuoyiOffice(七):上线篇——从测试验收到部署上线,完成企业项目交付

🌐 文档地址:https://ruoyioffice.com
 👇 文章底部获取源码和演示地址 👇
 💬 :17156169080(获取产品咨询)

这是《7天学会SpringBoot+Vue3企业级项目RuoyiOffice》系列第 7 篇,也是最后一篇。前六天我们在开发机上做出了一个有页面、有权限、有审批的用车申请模块,但它还只在“自己的电脑”上成立。第七天要把它交付出去:配置怎么分环境、产物怎么打、Nginx 怎么配、密钥放哪里、日志去哪看、出了问题怎么退回去。读完你能回答三个问题:上线前后到底要核对哪些配置,上线当天按什么顺序做、每一步怎么判断过没过,上线后出了故障先看哪里。

▲ 本篇核心视觉:左侧是访问方;中间虚线框是公网入口层,只有 Nginx;右侧虚线框里的后端、MySQL、Redis 和文件存储只监听本机或私网。下半区左边是微服务形态,右边是发布之后每天要用的运维入口。红色虚线框是两个最容易出事故的点。

引言:上线不是把 jar 拷过去

开发环境里能跑,是因为很多“方便调试”的开关是开着的:验证码关闭、可以用模拟令牌登录、Swagger 和监控端点全部暴露。生产环境恰好要把这些统统反过来。上线真正要做的是三件事:把开发期的便利开关换成生产的安全基线,把产物放到正确的位置并让入口能转发,再用一套固定的验收动作确认它真的可用。

动手之前,先把几个决策摆出来:

决策点
可选项
本文的取舍
理由
部署形态
单体、微服务
主线讲单体,微服务只讲差异
单机即可交付,运维面最小;微服务要 4 台以上主机,适合有拆分诉求的客户
后端运行方式
systemd 直接跑 JAR、Docker Compose
两者都给,以 systemd 为样例
部署手册两条路径都支持,原理相同,区别只在进程由谁托管
前端分发
Nginx 托管静态文件、前后端同进程
Nginx 托管
前端更新只需替换目录,不必重启后端
浏览器访问后端
同域反代、浏览器直连后端端口
同域反代
避免跨域,后端端口也不必对公网开放
配置与密钥
写进配置文件、环境变量或外部配置
环境变量或外部配置
配置文件会进仓库,密钥不能进仓库

说明:本文引用的配置、脚本和类,来自仓库里的 application-prod.yaml、logback-spring.xml、pom.xml、.env.production、部署手册和 yudao-framework 源码,为便于阅读做了节选。我没有在真实服务器上把这套流程完整执行一遍,凡是“示例”“建议”的命令,文中都会标明,上线前请先在测试环境走通。

一、先分清环境:dev、demo、prod

仓库的后端配置按 Spring profile 拆成多份:application-local.yaml、application-dev.yaml、application-demo.yaml 和 application-prod.yaml,公共部分在 application.yaml。仓库里没有名叫 test 的 profile,所以“测试环境”要么用 prod 配置配一个独立的测试库来预演,要么自己约定一个 profile,不要拿 dev 当测试环境,因为它的安全开关是关着的。

下面这张表是我逐份读配置整理出来的差异,上线时最该盯的是后四行:

配置项
local / dev
demo(演示站)
prod(客户生产)
上线风险
yudao.captcha.enable false false true
带入开发值会让登录失去验证码保护
yudao.security.mock-enable true true false
开着时可用模拟令牌登录
Actuator 暴露端点
全部
全部
仅 health、info、metrics
全部暴露会泄露环境与 Bean 信息
Druid 监控控制台
开启
开启(白名单为空)
关闭
弱口令监控页暴露在公网
Swagger / Knife4j
继承基础配置,开启
继承基础配置,开启
关闭
接口文档对外可见
Flowable 自动建改表
继承基础配置,开启
继承基础配置,开启
关闭
生产表结构应只由交付 SQL 变更
yudao.access-log.enable false false false
三者都默认不落库,排障时按需临时打开

这里有一个必须当场处理的陷阱:仓库自带的 yudao-server/docker-compose.yml 是开发与演示样例,它有两处和生产要求相反——

  • SPRING_PROFILES_ACTIVE
     默认值是 demo,不显式改成 prod 就会带着演示站的开关上线;
  • MySQL、Redis 和后端的端口映射写成了 "3306:3306"、"6379:6379"、"48080:48080",会对所有网卡开放,而部署手册要求这些端口只绑定 127.0.0.1,公网只开 22、80、443。

所以拿这份 compose 上生产之前,至少要改 profile 和端口绑定两处,改完之后用外部端口扫描确认一遍。

二、单体还是微服务:取舍和差异

同一套代码可以按两种形态打包,区别由 Maven profile 决定。根目录 pom.xml 里这一段把差异写得很清楚:

<!-- 单体/微服务打包控制:true=单体模式(子模块跳过repackage),false=微服务模式 --><skip.repackage>false</skip.repackage>...<profiles>    <!-- boot 单体运行环境 -->    <profile>        <id>boot</id>        <properties>            <profile.name>boot</profile.name>            <skip.repackage>true</skip.repackage>        </properties>    </profile>    <!-- cloud 微服务运行环境(默认) -->    <profile>        <id>cloud</id>        <activation>            <activeByDefault>true</activeByDefault>        </activation>        <properties>            <profile.name>cloud</profile.name>            <skip.repackage>false</skip.repackage>        </properties>    </profile></profiles>

两点要读出来:默认激活的是 cloud,所以不写 -Pboot 打出来的是微服务形态;boot 会让各个子模块跳过 repackage,只有 yudao-server 自己打成可执行 JAR(它的 pom 里注明始终需要 repackage)。如果漏了这个参数,依赖模块也会被打成可执行包,部署手册里记录的现象就是 JAR 体积异常翻倍。

对比项
单体(-Pboot)
微服务(默认 cloud)
启动入口
yudao-server
,默认端口 48080
网关加各业务 *-server
最少节点
一台,手册基线 4 核 8G 起
手册要求不少于 4 台主机
必备中间件
MySQL、Redis
MySQL、Redis、Nacos,可选 RocketMQ
Nginx 上游
127.0.0.1:48080
网关,且不要剥掉 /admin-api
流程状态回写
默认本地事件即可
必须配置为 mq,禁止 local
适用场景
中小企业、单机交付
需要按模块独立发布和扩缩

最后一行就是第六篇讲的回写通道在部署上的落点:微服务下如果 yudao.bpm.notification.default-type 仍是 local,流程结束了,业务单据却可能一直停在“审批中”。部署手册说明微服务主路径用 Redis Stream 承载这条通知,不强制先装 RocketMQ。

三、构建:后端 JAR 与前端 dist

3.1 后端打包

生产机不需要装 Maven,构建放在开发机或 CI。单体打包命令来自部署手册,PowerShell 里 -D 参数要加引号:

cd ruoyi-officemvn clean package "-Dmaven.test.skip=true" "-Dskip.repackage=true" -pl yudao-server -am -Pbootls -lh yudao-server/target/yudao-server.jar

JAR 名来自 yudao-server/pom.xml 的 finalName,即 yudao-server.jar。工程编译级别是 Java 17,部署手册说明生产机用 JDK 17 或 21 都可以。

3.2 前端构建

PC 端在 ruoyi-office-vben 根目录用 pnpm build:antd 构建,实际执行的是 web-antd 里的 vite build --mode production,随后跑一个预压缩脚本生成 .gz 文件,供 Nginx 的 gzip_static 使用。决定产物行为的是 apps/web-antd/.env.production,节选关键项:

VITE_BASE=/VITE_BASE_URL=/webVITE_GLOB_API_URL=/admin-apiVITE_UPLOAD_TYPE=serverVITE_ROUTER_HISTORY=hashVITE_APP_CAPTCHA_ENABLE=trueVITE_APP_DOCALERT_ENABLE=falseVITE_GLOB_DEMO_ENABLE=falseVITE_APP_DEFAULT_USERNAME=VITE_APP_DEFAULT_PASSWORD=# 构建命令:#   cd ruoyi-office-vben#   pnpm install#   pnpm build:antd# 产物目录:apps/web-antd/dist(以构建输出为准)

这几行对应着三个上线动作:

  1. VITE_GLOB_API_URL=/admin-api
     是相对路径,浏览器会连当前域名,由 Nginx 转给后端,所以前端包不需要随域名重新构建;
  2. 路由是 hash 模式,页面地址形如 /web/#/...,刷新不会触发 Nginx 的回落规则,但 /web/ 本身必须能找到 index.html;
  3. 演示横幅、文档提示条、登录页预填账号密码都在生产构建里是关闭或为空,别用 build:demo 的产物上客户环境。

两处与部署手册不一致,以仓库为准:手册示例里写的是 VITE_BASE_URL=(空),仓库实际是 /web;手册写 Node 20.19 以上、pnpm 10 以上,而仓库 package.json 的 engines 要求 Node 22.18 及以上的 22 系或 24 系,pnpm 11 及以上。装环境前请以 package.json 为准。

四、Nginx:静态文件、接口反代与 WebSocket

入口层只负责三件事:托管 /web/ 静态文件,把 /admin-api 转给后端,把 /infra/ws 以 WebSocket 方式转给后端。下面是根据部署手册的最小配置节选整理的两个 location,其中带注释的一行是我的建议,不是仓库自带:

location /admin-api {    proxy_pass http://127.0.0.1:48080/admin-api;    proxy_set_header Host remote_addr;    proxy_set_header X-Forwarded-For scheme;    # 建议追加:置空后 Nginx 不会把该头转给上游(示例,需自测)    proxy_set_header login-user "";}location ^~ /infra/ws {    proxy_pass http://127.0.0.1:48080/infra/ws;    proxy_set_header Host proxy_add_x_forwarded_for;    proxy_set_header X-Forwarded-Proto http_upgrade;    proxy_set_header Connection "upgrade";    proxy_read_timeout 3600s;    proxy_send_timeout 3600s;    proxy_buffering off;}

三个细节值得展开:

  • login-user 头。
     第五篇讲过,后端的令牌过滤器会优先信任请求头 login-user 来构造登录用户,本意是给网关和内部服务透传。单体直面浏览器时,Nginx 必须保证外部请求带不进这个头,上面那一行就是做这件事。仓库的部署手册没有写这一条;微服务下网关是否会先清除外部传入的该头,我没有核实,请上线前自行测试。
  • /infra/ws 路径。
     前端拼 WebSocket 地址时,用的是站点根的 origin 再拼上 /infra/ws,而不是 /web 下面。源码是这样写的:
/** * 构建 WebSocket 地址。 * * 生产环境前端部署在 /web 子路径下,VITE_BASE_URL=/web 只适用于 iframe 等前端子路径资源; * WebSocket 需要连到站点根路径下的后端代理 /infra/ws。 */export function buildWebSocketUrl(path: string, token?: string) {  const normalizedPath = path.startsWith('/') ? path : `/{MYSQL_URL:jdbc:mysql://127.0.0.1:3306/ruoyi-office?useSSL=false&serverTimezone=Asia/Shanghai&...}          username: {MYSQL_PASSWORD:请修改为现场密码}  # 注意:不要写 password: {REDIS_HOST:127.0.0.1}      port: {REDIS_DATABASE:0}flowable:  # 生产禁止自动建/改表,表结构以交付 SQL 为准  database-schema-update: false

按这份配置,能梳理出一张“该怎么给”的清单:

类别
变量或位置
注意
MySQL
MYSQL_URL
、MYSQL_USERNAME、MYSQL_PASSWORD
默认值是占位文字,不改会直接连不上
Redis
REDIS_HOST
、REDIS_PORT、REDIS_DATABASE,密码用 SPRING_DATA_REDIS_PASSWORD
无密码时不要注入空串
日志目录
LOG_PATH
不设则落在运行用户目录下的 logs
OnlyOffice
ONLYOFFICE_ENABLED
、ONLYOFFICE_SERVER_URL、ONLYOFFICE_JWT_SECRET、ONLYOFFICE_CALLBACK_BASE_URL
JWT 密钥要与 Document Server 一致
微信、第三方登录
WX_MP_*
、WX_MINIAPP_*、JUSTAUTH_*
按需填写,未用到的保持占位
前端加密
后端 yudao.api-encrypt 与前端 VITE_APP_API_ENCRYPT_*
两端的开关和密钥必须成对更换
,改了前端要重新构建

有两件事需要明确提醒:

  • 部署手册里 Compose 和 systemd 的示例传的是 REDIS_PASSWORD,但 application-prod.yaml 只读 REDIS_HOST、REDIS_PORT、REDIS_DATABASE,不读 REDIS_PASSWORD。按配置文件推断,Redis 有密码时应使用 SPRING_DATA_REDIS_PASSWORD;仓库自带 compose 的注释也是这样写的。这是我读配置得出的结论,没有在真机上验证。
  • 基础配置 application.yaml 里带有示例用的加解密密钥,前端 .env 里也有一份与之配对的值。它们写在仓库里就等于公开,生产必须两端一起更换。文中不复述这些值。

systemd 托管后端时,建议把密钥放进只有运行账号可读的环境文件,而不是写在单元文件里。下面的单元文件在部署手册示例的基础上,把内联的 Environment= 改成了 EnvironmentFile=,并把运行账号改成低权限账号,这两处是我的调整:

# /etc/systemd/system/yudao-server.service[Unit]Description=YuDao ServerAfter=network.target mysql.service redis.service[Service]Type=simple# 手册示例是 root,建议改为专用账号,并授权 /data/appUser=yudaoWorkingDirectory=/data/app# 环境文件权限 600,内容为 MYSQL_URL、MYSQL_PASSWORD、# SPRING_DATA_REDIS_PASSWORD、LOG_PATH 等,不进 GitEnvironmentFile=/data/app/yudao.envExecStart=/usr/bin/java -Xms512m -Xmx2048m -jar /data/app/yudao-server.jar --spring.profiles.active=prodRestart=on-failureRestartSec=10[Install]WantedBy=multi-user.target

六、中间件:MySQL、Redis、对象存储、MQ 与定时任务

组件
单体里的角色
上线要点
MySQL
业务库,字符集 utf8mb4
导入 ruoyi-office-db/dump/latest/ 里的结构和静态数据;禁止导入演示站业务库,里面有演示账号和脏数据;端口只绑本机
Redis
令牌、缓存、分布式锁、消息流
端口只绑本机;有密码时用 SPRING_DATA_REDIS_PASSWORD
文件存储
附件、头像、模板
本地盘或 OSS、MinIO 等 S3 兼容存储,二选一设为“主配置”
消息队列
部分模块事件总线
可选;配置里 RocketMQ 地址默认是本机,未部署时启动日志可能有连接警告
定时任务
考勤生成、订单过期、日志清理等
xxl.job.enabled
 在 prod 默认 false;启用需独立库 xxl_job,调度中心只绑本机

文件存储是最容易“能传不能看”的一环。管理端的入口在“基础设施 → 文件管理 → 文件配置”:

▲ 文件配置列表。同一时刻只有一条“主配置”生效,这张截图里被标成“是”的是阿里云示例;备注栏写着“请换成你的密钥”,说明这些云厂商条目只是示例,不能直接带上生产。上线时应新增客户自己的配置,点“测试”通过后再设为主配置。

本地盘方案要确认两件事:基础路径(部署手册建议 /data/app/upload)存在且后端可写;“自定义域名”填浏览器能访问的地址,不要填后端本机地址,否则局域网用户打不开附件。

定时任务有一个容易忽略的连带关系。仓库里清理接口访问日志的任务 AccessLogCleanJob 是 XXL-Job 任务,说明写的是“物理清理超过 14 天的接口访问日志”。如果 prod 保持 xxl.job.enabled: false,按常理推断这类清理任务就不会被调度,访问日志一旦被你临时打开排障、忘了关,表会一直长。这是推断,未实测。

七、日志与排障:四层日志各管什么

线上出问题,第一反应是“看日志”,但要知道在哪一层看。这套系统有四层:

层次
记录什么
在哪看
默认状态
应用日志
框架与业务的运行日志
LOG_PATH
 下的 yudao-server.log;Docker 要把该目录挂载出来
prod 只写文件,不写控制台
访问日志
每次接口调用的用户、地址、耗时
管理端“系统运维 → API 日志 → 访问日志”
三个环境配置里都是关闭
错误日志
全局异常处理器捕获的异常
管理端 API 日志里的错误日志
异常发生时异步入库
操作日志
业务操作留痕,如“创建用户”
管理端“审计日志 → 操作日志”
由方法上的 @LogRecord 注解产生

应用日志的滚动规则写在 logback-spring.xml 里,这是一次真实踩坑后加上的保护,注释里记录了“误删后演示站再次写满磁盘”的教训:

<!-- 滚动策略:基于【每天 + 大小】创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">    <fileNamePattern>{LOG_PATH},Docker 部署时要把它和挂载目录对齐。访问日志由 YudaoApiLogAutoConfiguration 里的条件注解控制,只要配置 yudao.access-log.enable=false 就不会注册这个过滤器。需要排查“某个用户某个接口为什么慢”时,可以临时打开,排完关掉:▲ 访问日志页。执行时长列能直接定位慢接口,“详情”可以看到完整的请求与响应元数据。注意这张截图的数据时间是 2024 年,来自较早的环境,仅用来展示页面形态,不代表当前线上数据。操作日志则回答“谁在什么时候改了什么”,也是客户验收时经常要看的审计证据:▲ 操作日志列表。每条记录带操作人、模块、操作内容、业务编号和操作 IP,内容是“创建用户”这类业务语言,而不是原始接口路径,这类记录来自 service 方法上的 @LogRecord 注解。常用的排障入口汇总如下:现象先看哪里命令或页面后端起不来应用日志文件,再看进程输出tail -f 日志文件;再看 journalctl -u yudao-server -f 或 docker logs -f yudao-server接口 500错误日志页与应用日志管理端错误日志;日志文件里搜异常类名某接口很慢临时打开访问日志访问日志页按“执行时长”排序某数据被改操作日志按业务编号或操作人筛选入口不通Nginx 日志/var/log/nginx/error.log 或容器内日志八、数据库备份与恢复部署手册的验收清单里只写了“备份 cron 已配置(库 + upload 目录)”,并没有给出脚本。下面是我给的示例,思路是三样东西同时备份:数据库、上传目录、当前运行的 JAR 与静态目录。密码放进权限为 600 的客户端配置文件,不要出现在命令行里。示例未在真机上执行:# 备份(示例,未实测)。/data/backup/.my.cnf 含账号密码,权限 600STAMP=STAMPmysqldump --defaults-extra-file=/data/backup/.my.cnf \  --single-transaction --routines --triggers \  --default-character-set=utf8mb4 ruoyi-office \  | gzip > /data/backup/STAMP/upload.tgz -C /data/app uploadcp /data/app/yudao-server.jar /data/backup/STAMP/web-dist.tgz -C /data/nginx/html web# 恢复演练:只导入到演练库,确认可读后再决定是否覆盖生产库gunzip -c /data/backup/$STAMP/ruoyi-office.sql.gz \  | mysql --defaults-extra-file=/data/backup/.my.cnf restore_check三个原则:备份要定时,更要做恢复演练,没演练过的备份只能算“可能能用”;升级前必备份,因为 prod 关闭了 Flowable 的自动改表,表结构只由 SQL 变更,一旦执行出错只能靠备份回退;增量升级 SQL 默认只执行归档目录里 01_apply_必跑 一类,02_optional_可选需确认 要逐条评估。九、发布流水线:七步走完才算上线把前面的内容串成一条固定流水线。每一步都有出口条件,不满足不进入下一步:▲ 发布流水线。七个方框从左到右依次推进;最右边的“放行或回滚”如果出现红灯,虚线箭头回到“上传切换”,换回上一版产物后重新走启动自检和冒烟回归。图下方列了上线当天最常见的三类现象和第一步该看的位置。步骤动作出口条件1 构建产物后端 -Pboot 打 JAR,前端 pnpm build:antdJAR 与 dist 都生成,产物带版本号归档2 备份现网备份库、上传目录、旧 JAR、旧 dist能说出每一份备份放在哪、怎么恢复3 配置与密钥选 prod,注入环境变量,换默认口令配置核对表全部勾选4 上传切换上传产物,重启后端,替换静态目录只改了 Nginx 配置才需要 nginx -t 并 reload5 启动自检看日志、探活日志出现 Started,/actuator/health 返回 UP6 冒烟回归按下文七项用例执行全部通过7 放行或回滚判定全绿放行,任一红灯回滚十、上线前验收清单与回归用例验收清单整理自部署手册里的“上线验收清单”,按“检查项、通过标准”两列使用,实施时建议另加一列“证据”,写截图或命令输出的位置:分组检查项通过标准连通入口能打开登录页/web/ 可打开并登录连通接口经 Nginx 正常网络面板里 /admin-api 无 502安全端口暴露公网扫描 3306、6379、48080、8080、8081 与 Nacos 均不可达安全生产 profile后端 prod,前端 production 构建,无“演示环境”横幅安全开发开关验证码开启,mock-enable 为 false,Swagger 与 Druid 控制台关闭,Actuator 不是全部暴露安全默认口令admin 与库、Redis、Nacos 等密码都已更换存储文件配置主配置指向本地盘或客户对象存储,上传后能预览业务菜单与列表菜单和列表正常加载业务审批一条审批流能走完;微服务下 BPM 通知为 mq运维备份备份任务已配置,且做过一次恢复演练清单里的“登录”是第一道门。生产构建的登录页不应预填账号和密码,前后端的验证码开关也要一致:▲ 登录页。生产构建下 .env.production 里默认账号与密码都是空的,所以这里不应出现预填内容;是否弹出滑块验证码,取决于后端 yudao.captcha.enable 与前端 VITE_APP_CAPTCHA_ENABLE 是否一致。这张图用来对照验收,不代表某一个客户现场。冒烟之外,我建议固定七项回归用例,每次发布都按同一顺序执行:用例怎么测通过标准失败先查登录用非 admin 的普通账号登录进入首页,刷新页面后仍保持登录验证码前后端开关;Redis 连接菜单切换几个模块菜单菜单与页面都能打开,无 404/web 的 alias 与 try_files;菜单组件路径权限用无权限账号访问受限按钮与接口按钮不出现,接口返回无权限角色菜单授权;权限标识是否与注解一致流程提交一张用车申请,审批通过单据状态同步为审批通过BPM 通知类型;监听器前缀;日志里的回写异常附件上传超过 1MB 的文件并预览上传成功,预览地址可访问client_max_body_size;文件配置的自定义域名消息登录后让另一人触发一条待办页面实时出现提示/infra/ws 是否返回 101;升级头与超时移动端用手机登录并发起一张单据能登录、上传、提交VITE_SERVER_BASEURL 是否为带协议的绝对地址十一、监控与回滚监控本文只讲最低限度,能在仓库里直接核对到的有这些:探活:/actuator/health,prod 暴露的端点只有 health、info、metrics,Docker 的 healthcheck 就是调用它。内置监控页:管理端“监控中心”里有 Redis 监控,能看版本、内存、命令统计。默认没有开的:Druid 控制台在 prod 关闭;Spring Boot Admin 的客户端在 prod 配置里是 enabled: false;SkyWalking 的日志追加器在 logback-spring.xml 里是注释状态。需要时再按合同开启,不要为了“看着全”而打开。▲ Redis 监控页。概览里能看到单机模式、端口、客户端数、键数量和持久化状态,下方是内存仪表盘与命令统计。这张截图来自某个开发环境:其中 AOF 显示为“否”,命令统计里出现了 xreadgroup,说明有组件在用 Redis Stream 消费;它具体由哪个组件产生,我没有逐一核实。主机层面的告警(磁盘、内存、进程存活)本文不展开,最低限度建议对 /actuator/health 做定时探活,并对数据盘设水位告警。回滚回滚不是“重新部署一次”,而是换回上一版已验证过的产物。顺序是:停后端(或直接替换后重启);把备份的 yudao-server.jar 放回原位,把备份的静态目录换回;重启后端,重新走“启动自检”和“冒烟回归”;只有这次发布执行过数据库变更、且旧版本无法兼容新表结构时,才恢复数据库备份,恢复前先确认会丢失哪一段时间的数据。微服务形态下,部署手册约定 /data/app/jars 目录保留回滚用的 JAR。数据库回退是破坏性操作,增量 SQL 里的 03_rollback_仅回滚 目录也只在明确需要时执行。十二、常见生产故障矩阵现象常见原因先看哪里处理页面 502 或 504后端没起来或端口不对curl 127.0.0.1:48080/actuator/health,再看后端日志修后端;确认 proxy_pass 端口/web/ 404 或白屏alias 路径不对、与 default.conf 冲突、静态文件未上传ls 看 index.html;nginx -T校正路径,nginx -t 后 reload后端启动后马上退出MySQL 或 Redis 连不上、密码不对、端口被占进程日志核对环境变量;Redis 密码用 SPRING_DATA_REDIS_PASSWORD页面好了但没有实时消息/infra/ws 没带升级头或被静态站拦截网络面板里的 WS 请求状态补 location,确认返回 101启动失败却看不到日志prod 只写文件,控制台没有输出LOG_PATH 指向的目录到日志文件里找;容器要确认挂载目录上传附件失败超过 client_max_body_size、目录无权限、主配置不对Nginx 日志;文件配置“测试”调大限制;修权限;改主配置附件能传但打不开“自定义域名”写了本机地址看预览请求的地址改成浏览器可访问的域名移动端上传报重复 /admin-apiH5 构建把接口地址写成了相对路径看最终 JS 产物里的接口地址改为带协议的绝对地址并重新打包流程结束了单据仍“审批中”微服务下 BPM 通知仍是 local;或回写异常被吞配置与日志里的回写异常改为 mq 并确认 Redis Stream;排查监听器登录后仍有“演示环境”横幅误用了 demo 构建看前端构建模式用 production 重新构建磁盘写满日志无上限或访问日志长期打开日志目录与 Docker 日志保留 totalSizeCap;限制 json-file 大小JAR 体积异常大构建漏了 -Dskip.repackage=true看产物大小按单体命令重新打包在线编辑器报 Editor.bin 404没反代 /cache/、/coauthoring/Nginx 配置补 location,proxy_pass 用服务名十三、本文发现的几处不足与需要人工确认的事仓库自带 compose 与部署手册要求相反。 默认 profile 是 demo,三个端口对全部网卡开放。本文只指出了问题,没有改它;上线要用的应是客户交付包里的 compose,或自己改过的版本。Redis 密码变量名不一致。 手册示例用 REDIS_PASSWORD,prod 配置读的是 SPRING_DATA_REDIS_PASSWORD。结论来自读配置,未真机验证,建议更新手册。手册与仓库对前端环境的描述不一致。 Node、pnpm 版本和 VITE_BASE_URL 的示例值都与仓库实际不同,本文以仓库文件为准。后端跨域对任意来源开放并允许凭证。 在“端口不对公网”的前提下问题不大,但这个前提要靠验收清单里的端口扫描来保证。示例密钥在仓库里。 基础配置与前端 .env 里带有配对的加解密示例密钥,生产必须成对更换。WebSocket 令牌在 URL 查询串里。 部署手册的 /infra/ws location 没有关闭访问日志,Nginx 的访问日志会记录带令牌的 URL。建议给该 location 加 access_log off,或在日志里脱敏。这一点未在真机验证。WebSocket 消息发送默认是本地模式。yudao.websocket.sender-type 默认值是 local,后端起多个实例时,需要改成 redis 或某种 MQ 才能互相转发。单实例不受影响。手册的日志位置与 prod 日志配置不完全吻合。 手册写“JAR 加 systemd 用 journalctl、Docker 用 docker logs”,但 prod 的 logback 只写文件、不写控制台,应用日志的主要位置是 LOG_PATH 下的文件。这一点我是从配置推断的,没有真机验证,两处都看最稳妥。没有真实部署验证。 本文所有命令与结论来自阅读配置、源码和现有文档与截图,没有在真实服务器上完整跑过一遍。示例命令(备份、systemd 的环境文件、Nginx 置空 login-user)上线前请先在测试环境验证。十四、今天学完你应该能做到说清 local、dev、demo、prod 在验证码、模拟登录、监控端点上的差异,并能指出 compose 样例里要改的两处。用 -Pboot 打出单体 JAR,用 pnpm build:antd 构建前端,解释 skip.repackage 的作用。写出托管 /web/、反代 /admin-api 与 /infra/ws 的 Nginx 配置,并说出切 HTTPS 后要同步改的四处。用环境变量管理数据库与 Redis 密码,知道哪些密钥要成对更换。区分应用日志、访问日志、错误日志、操作日志,并按现象选入口。做一次备份并做一次恢复演练,按七步流水线发布,出现红灯时能回滚。常见问题(FAQ)测试环境应该用哪个 profile?仓库没有 test profile。建议测试环境使用 prod 配置,连独立的测试库,这样验证的就是生产的安全基线。dev 和 local 的验证码、模拟登录等开关是为开发调试准备的,不适合做验收。前端换域名需要重新构建吗?PC 端不需要。VITE_GLOB_API_URL 是相对路径 /admin-api,浏览器会连当前域名。需要重新构建的是 UniApp H5,它要求接口地址是带协议的绝对地址,换域名必须重新打包。一定要上微服务吗?不需要。单机、单体即可交付,部署手册对单体的基线是 4 核 8G 起。微服务适合需要按模块独立发布和扩缩、并且有 4 台以上主机的客户。选微服务时记得把 BPM 通知改成 mq。后端端口为什么不能对公网开放?一是后端自带的跨域配置允许任意来源带凭证访问,二是令牌过滤器会信任 login-user 请求头。把端口只绑到本机,所有流量都经过 Nginx,这两个风险才有收口的地方。访问日志默认是关的,线上怎么排查慢接口?临时把 yudao.access-log.enable 打开并重启,排查完关闭。若没有启用 XXL-Job,清理任务不会被调度,要记得及时关,必要时手动清理历史数据。系列进度与全文回顾篇目主题状态(一)架构篇——一个底座,多端通达已发布(二)启动篇——从源码到前后端联调,跑通开发环境已发布(三)后端篇——从业务建模到接口开发,做出一个完整模块已发布(四)前端篇——从菜单路由到表单列表,完成业务页面已发布(五)权限篇——把登录、角色、数据权限与租户隔离讲透已发布(六)流程篇——接入审批,让业务单据真正流转起来已发布(七)上线篇——从测试验收到部署上线,完成企业项目交付本篇七天走下来,是同一条主线:先在架构篇认清多端共用一个底座,在启动篇把环境跑通,在后端篇和前端篇做出一个完整的用车申请模块,在权限篇划清谁能看什么,在流程篇让单据真正流转,最后在上线篇把它交付到生产。如果你要继续深入某一环,可以回到对应篇目,或者查阅文档站里的部署指南与上线文档。如果这篇对你有用,点个「在看」或收藏。打开演示地址直接查看系统。

【声明】内容源于网络
0
0
企业软件源码
RuoyiOffice 是一套基于 Spring Boot + Vue3 +Uniapp 的企业一体化管理平台,集 OA、CRM、ERP、工作流、HR、资产、合同、项目、AI应用等业务于一体,帮助企业用一个系统协同管理多类核心业务。
内容 144
粉丝 0
企业软件源码 RuoyiOffice 是一套基于 Spring Boot + Vue3 +Uniapp 的企业一体化管理平台,集 OA、CRM、ERP、工作流、HR、资产、合同、项目、AI应用等业务于一体,帮助企业用一个系统协同管理多类核心业务。
总阅读2.5k
粉丝0
内容144