若伊框架生产部署:Tomcat+Nginx分离静态资源实战
1. 先想清楚若伊这套框架到底该怎么部署才合理很多朋友拿到若伊RuoYi框架的第一反应是往服务器上扔代码然后问我“我该用Tomcat还是Tomcat加Nginx”说实话这个问题没有标准答案取决于你是想在本地跑通演示还是让它在生产环境稳定扛流量。我自己的结论很明确单机演示用纯Tomcat足够但凡要上线、要给人用老老实实走TomcatNginx。这套框架脱胎于Spring Boot默认开发阶段我们用mvn spring-boot:run就能起来为什么还要谈部署方式因为框架里既有后端Java代码又有前端Vue打包出来的静态资源。部署的本质问题是谁负责跑Java逻辑谁负责喂静态文件谁对外暴露统一入口。这些角色分得越清楚后面扩容、排查问题就越轻松。如果走纯Tomcat部署一般有两种做法。一种是改造成war包丢进webapps目录让Tomcat的Servlet容器接管一切另一种是仍旧打成jar包但把前端dist里的静态文件拷到src/main/resources/static下重新打包让Spring Boot内置的Tomcat一把梭。这两种方案都能让若伊跑起来但都有一个共同短板静态资源全部压在Tomcat的线程池上图片稍微多几个、并发稍微上来一点Tomcat默认的200个工作线程就容易被耗尽。引入Nginx之后情况完全变了。Nginx作为前置代理监听80或443端口接管浏览器请求纯静态文件图片、CSS、JS直接由Nginx处理只有带/api、/prod-api这类动态路径的请求才转发给后端的Tomcat。这是大多数若伊生产部署的标准形态也是本文要重点展开的主线。为了帮你做决策我整理了一个简单的判断表场景推荐方式理由本地开发、功能演示mvn spring-boot:run开发效率最高改完即生效内网小规模使用几十人纯Tomcat部署war包部署简单够用就好公网服务、有图片上传、并发过百TomcatNginx静态资源分离稳定性质变高可用、多实例业务Nginx负载均衡多TomcatNginx天然支持upstream扩容方便2. 杀人的环境准备JDK、Maven、前端构建一个都不能少部署若伊有一个隐蔽的坎——不是项目起不来是环境乱七八糟导致起不来。我第一次给别人部署时先被JDK版本坑了一把接着被前端node-sass编译失败折磨了两小时后来发现都是环境版本匹配的问题。所以我要把这一步单独拎出来说透。2.1 JDK版本别凭感觉选若伊官方很多版本基于Spring Boot 2.x底层对Java 8的支持最稳定。如果你的代码是当前比较新的RuoYi-Vue或者RuoYi-Vue-plus这类分支用JDK 8基本不会错要是用到了更新的Spring Boot 3.x版本那要求JDK 17起步。在动手之前先打开pom.xml看java.version标签按这个来装JDK不要凭“最新版肯定好”的感觉装个JDK 21。Linux服务器上验证JDK是否可真执行java -version echo $JAVA_HOME如果JAVA_HOME是空的即使java -version能打印很多构建工具一样会翻车。建议编辑/etc/profileexport JAVA_HOME/usr/local/jdk1.8.0_202 export PATH$JAVA_HOME/bin:$PATH保存后执行source /etc/profile再看一遍。这一步省不了Maven打包时要靠JAVA_HOME定位编译器。2.2 Maven打包跳过测试是常规操作但不是偷懒项目根目录下执行mvn clean package -Dmaven.test.skiptrue这里要注意-Dmaven.test.skiptrue会跳过测试代码的编译和运行-DskipTests只是跳过运行、但仍编译测试类。对于部署场景前者更快更省心。国内网络环境拉Maven依赖经常卡住建议在settings.xml里配阿里云镜像mirror idaliyunmaven/id mirrorOfcentral/mirrorOf urlhttps://maven.aliyun.com/repository/public/url /mirror配完之后构建速度天壤之别。打完包在ruoyi-admin/target/目录下会看到jar包或war包这就是我们要的产物。2.3 前端构建别把dist拷错地方若伊Vue版本的前端在ruoyi-ui目录下。本地或服务器上执行npm install npm run build:prod执行完会在ruoyi-ui/dist下生成静态文件。如果npm install卡在node-sass这类原生模块上多半是Node版本不对——老的若伊前端对Node 14、16较友好新版RuoYi-Vue3则建议Node 16。node-sass编译失败的解决办法通常是npm uninstall node-sass npm install sass --save-dev改完再重新npm install。构建成功后把dist整个目录记下来后面部署时要把这里的index.html、static、favicon.ico等文件处理掉不要让它们静静躺在服务器某个角落。2.4 Linux侧的基础依赖还要保证服务器上有unzip、tar、vim、lsof这类基础工具尤其是lsof排查端口占用离不开它。用YUM安装yum install -y unzip tar vim lsof如果服务器是Ubuntu系就用apt-get install。这一步用不了半分钟但能省掉后续很多“命令找不到”的尴尬。3. 纯Tomcat部署war包流程、验证与首次启动的坑先讲清楚纯Tomcat方案因为它的逻辑最简单也是理解TomcatNginx方案的基础。把若伊改造成war包部署网上资料不少但很多教程漏了关键步骤导致启动后访问一直404。3.1 从jar包到war包要改三个地方第一处在ruoyi-admin/pom.xml里把默认打包方式改掉packagingwar/packaging第二处因为Spring Boot内置Tomcat会和外部Tomcat冲突得把内置容器标记为provided最常见的写法是在spring-boot-starter-tomcat依赖上加dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-tomcat/artifactId scopeprovided/scope /dependency第三处在启动类RuoYiApplication上继承SpringBootServletInitializer并重写configure方法。这是让外部Tomcat能找到应用入口的关键SpringBootApplication public class RuoYiApplication extends SpringBootServletInitializer { Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(RuoYiApplication.class); } public static void main(String[] args) { SpringApplication.run(RuoYiApplication.class, args); } }这三处改完重新执行mvn clean package -Dmaven.test.skiptrue在ruoyi-admin/target/下会生成ruoyi-admin.war。3.2 部署到Tomcat目录与启动把war包上传到Tomcat的webapps目录然后启动。以Tomcat 8.5/9为例cd /usr/local/tomcat/bin ./startup.shTomcat会自动解压war包生成同名的ruoyi-admin目录。首次启动时若伊的后端默认端口是8080但注意它有独立的context-path默认是/所以理论上访问地址是http://服务器IP:8080/实际上你在项目配置里如果看到server.servlet.context-path被设置为/prod-api这类值那就要靠路径区分了。部署时不调整的话纯Tomcat方案的访问路径应该是http://IP:8080/如果配置了context-path那就访问http://IP:8080/prod-api/但登录页通常是直接访问根路径也就是说前端页面和接口路径可能不在同一个根下面这一点后面踩坑时会专门提。3.3 首次启动的坑为什么页面白屏好多人走到这一步启动日志也刷了页面就是白屏检查过程发现Tomcat在跑但index.html永远404。问题多半是前端静态资源没进war包。war包部署方案里前端dist文件要放到ruoyi-admin/src/main/resources/static目录下再一起打包。如果只改了后端配置、忘记把dist塞进static目录那么后端起来了也没有可访问的前端页面。验证方法很直接curl -I http://127.0.0.1:8080/如果返回200并且能看到index.html说明静态资源位置对了。如果404解压war包看看cd /usr/local/tomcat/webapps/ruoyi-admin ls WEB-INF/classes/static/static目录下没有前端文件那就在ruoyi-admin/pom.xml加资源拷贝配置或者干脆把dist目录直接复制到src/main/resources/static下重新打包。3.4 纯Tomcat方案的验证检查单启动完成后我习惯按这个顺序来一遍进程是否存在ps -ef | grep tomcat端口是否监听lsof -i:8080日志是否有异常tail -f /usr/local/tomcat/logs/catalina.out页面是否可访问curl -I http://127.0.0.1:8080后端接口是否通curl -X POST http://127.0.0.1:8080/login -H Content-Type: application/json -d {username:admin,password:...}以上能过说明纯Tomcat部署算成功了。但如果你要问生产环境能不能这么干——能不过遇到高峰期有概率出现页面加载慢、图片卡顿。这就是我们下一节要聊的Nginx的价值。4. Nginx只是反向代理不它决定了若伊的生产可用性很多教程把TomcatNginx说成“用一个Nginx反向代理Tomcat”这个描述没错但它等于没说因为Nginx给若伊带来的价值远不止“转发请求”这一件事。4.1 Tomcat的软肋静态资源挤占线程Tomcat是Servlet容器它设计上是跑动态请求的。部署若伊后一秒钟几十个请求打过来如果每个请求都包含一堆JS、CSS、图片Tomcat的线程池立刻被这些静态请求占满动态接口反而排队。你可以做个小实验纯Tomcat部署下用浏览器无缓存刷新页面打开Network面板能看到vendor.js这个文件轻松超过1MB本地加载可能只要几百毫秒但在服务器带宽有限的情况下这一个文件就要占用Tomcat连接线程好几秒。这段时间里其他用户登录、查询数据的请求只能等着。Nginx处理静态文件几乎不耗Java线程它的事件驱动模型扛静态请求非常擅长一个worker进程可以同时处理几万个连接。把静态文件这摊事从Tomcat身上剥离等价于把Tomcat的全部CPU和线程留给业务接口。4.2 统一入口和端口复用的现实价值如果服务器上只跑若伊用8080直接对外也不是不能用。但现实是一台服务器可能还跑着别的服务或者同一个公网IP上有多个域名。Nginx监听80/443按照server_name把不同域名分发到不同后端这样就实现了“一个公网入口多套服务分流”。这一步对运维的价值极大。以后若伊服务升级、重启Nginx不需要动如果哪天要把HTTP换成HTTPS只需要在Nginx层挂证书后端Tomcat一行配置都不用改。4.3 多实例部署时不加Nginx就麻烦大了纯Tomcat部署想要做集群扩容要么在前面加负载均衡器要么就得让用户手动访问不同端口。有了Nginx配置一个upstream就能在多台Tomcat之间做轮询。而且Nginx还能通过ip_hash实现简单的会话保持解决用户频繁掉登录态的问题。4.4 安全性层面Nginx是一道免费的“铁闸”Tomcat直接暴露到公网等于把应用服务器、版本信息、端口细节全摊给扫描器。Nginx前置后可以统一做请求体的最大尺寸限制防止恶意上传把Tomcat磁盘打爆。URL访问规则过滤拦截未授权路径。HTTPS终止让内部HTTP流量不暴露在公网。隐藏后端服务细节响应头上不会暴露Tomcat版本。所以我的建议很直接如果你打算让若伊正式给用户用别省掉Nginx这层。它解决的问题不是“多了几个功能”而是“让服务在真实流量下还立得住”。5. Nginx配置实操server块、静态资源分离与Gzip这一节是全文的重头戏。我将以典型的若伊部署目录和端口规划为例给你一份可以直接抄的Nginx配置并解释每一段配置背后的原因。我的规划是Tomcat跑在127.0.0.1:8080只允许本机访问。Nginx对外监听80端口。前端编译产物放在/home/web/ruoyi-ui/dist。若伊上传文件的访问路径是/profile/实际文件存储路径由后端配置指定。5.1 先装Nginx以CentOS/RHEL系为例直接YUM源通常没有nginx一般用官方源rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm yum install -y nginx systemctl start nginx systemctl enable nginx国内服务器也可以直接编译安装但需要额外装PCRE、zlib、openssl等依赖比较费时间。对大多数场景官方源安装足够。装完验证nginx -v curl -I http://127.0.0.1/看到Nginx欢迎页就说明装好了。Windows下部署则下载Windows版压缩包解压后运行nginx.exe即可不过请记住Windows下不要指望它跑生产级并发。5.2 完整的server配置这是我在实际项目里验证过的一份若伊Nginx配置upstream ruoyi_tomcat { server 127.0.0.1:8080 max_fails2 fail_timeout10s; } server { listen 80; server_name yourdomain.com; root /home/web/ruoyi-ui/dist; index index.html; client_max_body_size 50m; access_log /var/log/nginx/ruoyi-access.log main; error_log /var/log/nginx/ruoyi-error.log warn; # 前端静态资源 location / { try_files $uri $uri/ /index.html; } # 后端接口反向代理 location /prod-api/ { proxy_pass http://ruoyi_tomcat/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 60s; proxy_read_timeout 120s; } # 上传文件访问 location /profile/ { alias /home/ruoyi/uploadPath/; } # 静态资源带指纹缓存提升加载速度 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { expires 7d; add_header Cache-Control public, no-transform; } gzip on; gzip_types text/plain text/css application/javascript application/json image/svgxml; gzip_min_length 1k; }5.3 每一段的用意/prod-api/这个路径是若伊前端默认的请求前缀登录、业务接口全走这里。proxy_pass http://ruoyi_tomcat/;末尾的/非常关键它的作用是把/prod-api前缀剥掉后转发给后端。如果后端若伊的context-path就是/prod-api那就反过来proxy_pass后面不加/。这里最容易出错我的建议是先确认后端接口完整请求路径到底是什么再决定proxy_pass末尾是否带斜杠。try_files $uri $uri/ /index.html;这段是Vue前端路由history模式的标配。它确保刷新页面时Nginx不会把前端路由误判为真实文件路径而是统一回到index.html由前端路由接管。如果不写这一行用户一旦在/system/user这类页面按F5立刻404。/profile/是若伊上传文件的统一访问前缀。比如上传头像后后端返回的路径是/profile/avatar/2024/xx.jpgNginx直接把这段请求映射到磁盘目录/home/ruoyi/uploadPath/不需要经过Tomcat。这样做的性能提升非常显著图片请求完全不占后端线程。client_max_body_size 50m;这行特别重要。若伊里有Excel导入、文件上传功能默认Nginx的client_max_body_size是1m超过这个大小的请求会直接413。你既然要支持上传大文件就把它调大具体大小看你业务需要。gzip配置能压缩前端JS和CSS有些用户带宽一般压缩之后vendor.js从1MB变成200多KB首屏速度改善非常明显。5.4 配置完如何验证改完配置后先测语法再重载nginx -t nginx -s reload然后验证三条链路浏览器访问http://IP/能出登录页。登录后点菜单接口走/prod-api能正常返回数据。上传个头像再访问返回的/profile/xxx.jpg路径图片能直接打开。三条都通说明Nginx前后端分离配置整体是对的。如果第二条失败去看/var/log/nginx/ruoyi-error.log多半是proxy_pass的路径问题。5.5 SSL与双向认证的提醒热搜词里提到“nginx 配置自签名证书 ssl 交互式方法”和“ssl 双向认证tomcat”这里提个醒生产环境强烈建议给Nginx层配置HTTPS证书。用Let‘s Encrypt或者自签名证书都可以在Nginx的server块里加上listen 443 ssl; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key;如果你偏好交互式生成证书可以用openssl交互式工具按提示输入域名、组织信息即可。双向认证则涉及客户端证书签发与校验配置量更大需要时再单独展开。核心结论是TLS这层放在Nginx做比放在Tomcat做清爽得多年底扫漏洞时能少操一大半心。6. 从日志到端口部署后最常见的故障排查手册这部分是我自己部署若伊时反复踩过的坑每一条都对应过一个“折腾半宿”的深夜。我把它按现象分类方便你出问题时直接对号入座。6.1 页面打不开8080没监听还是防火墙没放行先从本地看端口lsof -i:8080 ss -lntp | grep 8080如果有监听再从外部访问。如果本机curl 127.0.0.1:8080有反应但公网IP访问不了九成是防火墙或服务器安全组拦了。在CentOS上firewall-cmd --zonepublic --add-port80/tcp --permanent firewall-cmd --zonepublic --add-port80/tcp --reload云服务器还要去控制台的安全组规则里把80端口开着。曾经有人把这条忘了来回检查了一天Nginx配置最后发现是安全组没放行教训深刻。6.2 404漂移三种情况若伊部署中404要区分三种位置访问/返回404是前端静态文件没放对。刷新某个具体页面404是try_files那行没配或配错。调用/prod-api下的接口返回404是前端请求的路径和后端context-path对不上。逐一排查时先用浏览器F12看Network面板看请求发到了哪个URL再顺着URL去Nginx配置里找对应的location规则。这个排查顺序能帮你少绕很多弯路。6.3 Tomcat乱码一个很容易“安慰自己”的问题日志里中文乱码、页面响应乱码原因可能出在三个环节Tomcat的日志编码、系统字符集、前端页面编码。Linux下推荐把JVM编码强制设为UTF-8在catalina.sh里追加JAVA_OPTS$JAVA_OPTS -Dfile.encodingUTF-8 -Dsun.jnu.encodingUTF-8同时确保系统locale不要是POSIX执行locale看一下如果输出里LC_ALL是空白在/etc/profile里加上export LANGen_US.UTF-8改完重启Tomcat再验证。至于Windows下开发时乱码那是控制台代码页问题与服务器部署无关不用混在一起看。6.4 502 Bad Gateway后端没起来或起的太慢Nginx配置没问题但所有接口都502基本可以断定后端Tomcat没起来或刚启动还没就绪。Spring Boot项目启动初期端口还没监听此时请求打到Nginx就会502。解决办法有两种一是等一会儿再试二是调大proxy_connect_timeout和proxy_read_timeout防止后端处理慢时Nginx过早断连。如果Tomcat进程崩溃去logs/catalina.out看异常栈。常见原因包括端口被占用、数据库连不上、Redis连接失败。若伊启动时强依赖MySQL和Redis这两个服务任何一个没就绪应用都可能启动失败或反复重试。6.5 用户上传的图片404图片404时先看后端返回的路径长什么样。如果是/profile/upload/2024/xx.jpgNginx里又没有location /profile/的规则那就会全部打到前端静态资源那里去结果自然404。检查一下alias路径是不是和若伊上传配置一致。若伊配置里有ruoyi: profile: /home/ruoyi/uploadPath这就是上传文件的真实落盘路径Nginx的alias必须指向它末尾记得带/。6.6 排查链路模版给新手一套我常用的排查命令链# 1. 看Nginx进程 ps -ef | grep nginx # 2. 看Nginx日志 tail -n 50 /var/log/nginx/ruoyi-error.log # 3. 看Tomcat日志 tail -n 100 /usr/local/tomcat/logs/catalina.out # 4. 看端口 lsof -i:80 lsof -i:8080 # 5. 直接测后端 curl -I http://127.0.0.1:8080/prod-api/ # 看有没有响应这套顺序的思路是从最外层入口逐层向内先确认Nginx是否正常转发再确认Tomcat是否正常处理最后把问题锁定在某一个环节。6.7 关于日志分析的一个建议若伊的日志文件默认在logs目录下按天滚动。真正排查问题时我习惯先把catalina.out里的ERROR和Exception抓出来grep -E ERROR|Exception logs/catalina.out | tail -n 50然后看业务日志里有没有SQL异常、Redis超时、权限报错绝大多数若伊生产问题都逃不出这几类。日志乱、问题杂的时候先别急着翻整本先锁定第一条异常顺着它往下追比什么都快。回到最初的问题若伊到底是纯Tomcat部署还是TomcatNginx我的答案一直是——看懂需求再选。但我个人把话放这儿我现在不管给谁部署若伊起步就直接上TomcatNginx省掉日后迁移带来的风险。顺便说个我的小习惯Nginx配置里永远用include /etc/nginx/conf.d/*.conf;管理每个服务的配置这样若伊的配置独立成一个文件以后停掉、改动、备份都不影响服务器上其他服务。你部署过几次就会明白这种细节才是真正能在凌晨两点救你命的东西。