
1. 项目概述与环境准备最近在国产化替代的浪潮下不少项目都开始要求在基于Linux内核的国产操作系统上进行部署比如银河麒麟、中标麒麟等。我手头一个典型的VueSpringBoot前后端分离项目就遇到了从熟悉的Windows开发环境迁移到麒麟系统的挑战。整个过程踩了不少坑也总结了一套相对通用的部署流程。如果你也正面临类似的任务无论是为了适配国产化环境还是单纯想在Linux服务器上部署你的全栈应用这篇从实战中摸爬滚打出来的经验应该能帮你省下不少折腾的时间。简单来说我们要做的就是把一个前端用Vue构建、后端用SpringBoot打包的Jar包项目完整地部署到一台全新的麒麟系统服务器上。这不仅仅是运行一个命令那么简单它涉及到系统环境配置、依赖安装、服务部署、网络打通以及后期的维护监控。整个过程可以拆解为几个核心环节首先是服务器基础环境的搭建包括Java运行环境、Node.js环境用于构建前端以及Web服务器如Nginx的安装其次是前后端代码的构建与部署最后是配置反向代理让前后端能够协同工作并通过系统服务实现开机自启。下面我就结合具体的操作步骤和踩过的坑带你走一遍完整的流程。1.1 核心需求与前置条件解析在开始动手之前我们必须明确目标和梳理清楚手头的资源。这个部署方案的核心目标是在麒麟系统上建立一个稳定、可维护的生产环境能够运行SpringBoot后端服务并对外提供由Nginx代理的Vue前端页面。首先你需要一台安装了麒麟系统的服务器。无论是物理机还是虚拟机确保你能通过SSH远程连接并拥有root权限或具备sudo权限的普通用户账号。这是所有操作的基础。其次明确你的项目代码状态。通常我们假设你已经在开发机上完成了前后端的编码和本地测试并且拥有一个可用的SpringBoot项目能够通过Maven或Gradle打包生成一个独立的、可执行的Jar文件例如your-app-0.0.1-SNAPSHOT.jar。一个Vue项目能够通过npm run build或yarn build成功生成静态资源文件通常位于dist目录下。服务器的网络环境也需要考虑。你需要知道服务器的IP地址并确保防火墙规则允许访问你计划使用的端口例如后端的8080端口和前端的80或443端口。如果服务器在局域网内还需要考虑域名解析或直接使用IP访问。注意强烈建议在正式部署前在本地或测试环境完整走通构建和部署流程。避免直接在生产服务器上边查边做容易引入错误和安全隐患。1.2 服务器基础环境检查与配置拿到一台新的麒麟服务器第一步不是急着装软件而是先做一次全面的“体检”。不同的麒麟系统版本如V10、V4可能基于不同的Linux发行版如CentOS、Ubuntu其包管理器和默认配置会有差异。通过命令cat /etc/os-release或uname -a可以查看系统详细信息。1. 系统更新与基础工具安装为了保证软件源的稳定性和安装过程的顺利首先更新系统包管理器并安装一些后续必备的工具。# 假设是基于CentOS的麒麟系统使用yum sudo yum update -y sudo yum install -y vim wget curl net-tools lsof # 如果是基于Ubuntu/Debian的麒麟系统使用apt sudo apt update sudo apt upgrade -y sudo apt install -y vim wget curl net-tools lsof安装vim是为了方便编辑配置文件wget和curl用于下载文件net-tools和lsof则是网络诊断和查看端口占用情况的利器。2. 防火墙与SELinux配置麒麟系统默认可能开启防火墙和SELinux这对于新手来说是两大“拦路虎”。为了简化初期部署我们可以先进行宽松配置待应用完全跑通后再细化安全策略。防火墙开放必要端口。# 查看防火墙状态firewalld sudo systemctl status firewalld # 开放端口例如80, 443, 8080 sudo firewall-cmd --zonepublic --add-port80/tcp --permanent sudo firewall-cmd --zonepublic --add-port443/tcp --permanent sudo firewall-cmd --zonepublic --add-port8080/tcp --permanent sudo firewall-cmd --reload # 如果使用iptables命令有所不同需根据系统调整。SELinux生产环境建议在充分了解后配置测试环境可临时设置为宽容模式。# 查看SELinux状态 getenforce # 临时设置为宽容模式重启失效 sudo setenforce 0 # 永久禁用需编辑 /etc/selinux/config将SELINUXenforcing改为SELINUXdisabled然后重启 # 注意永久修改有安全风险请谨慎评估。我的经验是在部署阶段如果遇到莫名其妙的“权限不足”错误而文件和目录权限明明正确多半是SELinux在作祟。暂时设为宽容模式可以快速定位问题。2. 核心依赖安装JDK、Node.js与Nginx基础环境就绪后就要安装运行我们项目的三大支柱Java环境、Node.js环境和Web服务器。2.1 安装Java运行环境JDKSpringBoot项目需要JRE或JDK来运行。生产环境推荐安装稳定的JDK版本如JDK 8、11或17。你可以选择安装系统源里的OpenJDK也可以从Oracle官网下载。方案一使用yum/apt安装OpenJDK推荐方便管理# 基于CentOS的麒麟系统 sudo yum install -y java-11-openjdk-devel # 以JDK11为例 # 基于Ubuntu的麒麟系统 sudo apt install -y openjdk-11-jdk安装后通过java -version和javac -version验证是否安装成功。方案二手动下载安装Oracle JDK如果项目对特定版本的Oracle JDK有要求可以手动下载。访问Oracle官网或可信镜像站下载对应版本的.tar.gz包如jdk-11.0.xx_linux-x64_bin.tar.gz。解压到指定目录例如/usr/local/java/。sudo tar -zxvf jdk-11.0.xx_linux-x64_bin.tar.gz -C /usr/local/java/配置环境变量。编辑/etc/profile文件在末尾添加export JAVA_HOME/usr/local/java/jdk-11.0.xx export PATH$JAVA_HOME/bin:$PATH使配置生效source /etc/profile然后再次验证java -version。实操心得生产环境强烈建议使用OpenJDK它完全开源且与麒麟系统的兼容性通常更好。手动安装JDK时务必注意解压路径和环境变量配置的准确性一个字符错误都可能导致命令找不到。2.2 安装Node.js与npm/yarnNode.js主要用于构建Vue前端项目。我们需要安装Node.js以及其包管理器npm。同样可以选择系统源安装或使用NodeSource仓库安装较新版本。方案一使用NodeSource仓库安装推荐版本新# 以安装Node.js 18.x为例 curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash - # 对于基于CentOS的系统 # 对于基于Ubuntu的系统命令类似请参考NodeSource官网 sudo yum install -y nodejs # 安装完成后验证 node -v npm -v方案二使用系统包管理器安装版本可能较旧但胜在稳定。# 基于CentOS的麒麟系统 sudo yum install -y nodejs npm # 基于Ubuntu的麒麟系统 sudo apt install -y nodejs npm如果系统源的Node.js版本过低Vue CLI可能需要Node.js 12建议采用方案一。安装yarn可选但推荐yarn是另一个高效的包管理器有时比npm更快、更稳定。npm install -g yarn yarn --version2.3 安装与配置NginxNginx将扮演两个角色一是作为静态文件服务器托管Vue构建出的dist目录二是作为反向代理服务器将前端对后端API的请求转发到SpringBoot应用。安装Nginx# 基于CentOS的麒麟系统 sudo yum install -y nginx # 基于Ubuntu的麒麟系统 sudo apt install -y nginx关键目录说明配置文件目录/etc/nginx/。主配置文件是nginx.conf通常我们会在/etc/nginx/conf.d/目录下为每个站点创建独立的.conf文件。默认网站根目录/usr/share/nginx/html。但我们通常会为项目创建专属目录。日志目录/var/log/nginx/。安装后启动Nginx并设置开机自启sudo systemctl start nginx sudo systemctl enable nginx此时在浏览器访问服务器IP应该能看到Nginx的欢迎页面这证明Nginx安装成功。3. 前后端项目构建与部署环境准备妥当现在开始处理我们的项目代码。通常我们不会在服务器上直接进行git clone和构建除非是自动化CI/CD流水线更常见的做法是在本地或构建服务器上完成构建然后将产物上传到生产服务器。3.1 后端SpringBoot项目打包与传输1. 本地打包在你的开发机上确保项目依赖都已下载然后使用Maven或Gradle打包。以Maven为例在项目根目录执行mvn clean package -DskipTests这会在target目录下生成一个可执行的Jar文件比如myapp-0.0.1-SNAPSHOT.jar。这个Jar包已经内嵌了Tomcat服务器和所有依赖是“一站式”的。2. 上传Jar包至服务器使用scp命令或SFTP工具如FileZilla将Jar包上传到服务器的一个专用目录。我习惯在/home下为应用创建一个目录。# 在服务器上创建目录 sudo mkdir -p /home/myapp/backend # 假设Jar包在本地使用scp上传从本地机器执行 scp target/myapp-0.0.1-SNAPSHOT.jar useryour_server_ip:/home/myapp/backend/3. 运行SpringBoot应用在服务器上进入该目录可以直接用java -jar命令运行。但为了更好的管理如后台运行、日志收集、开机自启我们通常将其配置为系统服务。简单测试运行cd /home/myapp/backend java -jar myapp-0.0.1-SNAPSHOT.jar # 使用 让它在后台运行。但这样管理不便且终端关闭后进程可能终止。使用curl localhost:8080或查看日志确认后端服务是否成功启动并在监听8080端口。3.2 前端Vue项目构建与部署1. 本地构建在Vue项目根目录下安装依赖并执行构建命令。构建会压缩和优化代码生成用于生产的静态文件。# 安装依赖如果已有node_modules可跳过 npm install # 或 yarn install # 执行构建 npm run build # 或 yarn build构建成功后项目根目录下会生成一个dist文件夹里面就是所有静态资源HTML, JS, CSS, 图片等。2. 上传静态资源至服务器同样将整个dist目录上传到服务器为前端准备的目录。# 在服务器上创建目录 sudo mkdir -p /home/myapp/frontend # 上传dist目录内容从本地机器执行 scp -r dist/* useryour_server_ip:/home/myapp/frontend/3. 配置Nginx托管前端现在我们需要告诉Nginx当用户访问网站时去/home/myapp/frontend这个目录找文件。 在/etc/nginx/conf.d/目录下创建一个新的配置文件例如myapp_frontend.conf。sudo vim /etc/nginx/conf.d/myapp_frontend.conf写入以下配置server { listen 80; server_name your_domain.com; # 如果没有域名可以用服务器IP或 localhost # 前端静态文件目录 root /home/myapp/frontend; index index.html index.htm; # 防止路由在刷新时出现404 location / { try_files $uri $uri/ /index.html; } # 配置静态资源缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control public, immutable; } # 可选配置后端API代理也可以单独配置见下一节 # location /api/ { # proxy_pass http://localhost:8080; # 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; # } }这个配置做了几件事监听80端口设置网站根目录配置了Vue Router的history模式支持try_files指令为静态资源设置了长期缓存以提高性能。保存并退出后测试Nginx配置语法是否正确sudo nginx -t如果显示syntax is ok和test is successful就可以重载Nginx配置使其生效sudo systemctl reload nginx现在访问服务器的IP地址或你配置的域名应该能看到Vue前端页面了。但此时页面里的API请求如果前端配置了/api这样的基础路径会直接发向前端服务器即Nginx的80端口而后端实际运行在8080端口所以会报404错误。接下来就需要配置反向代理来打通前后端。4. 配置Nginx反向代理与系统服务这是将前后端连接起来的关键一步也是配置的精华所在。4.1 配置Nginx反向代理后端API我们不建议在前端代码里直接写后端服务器的IP和端口而是通过Nginx统一转发。这样更安全、更灵活。修改上面创建的myapp_frontend.conf或者单独创建一个API代理配置。我更倾向于将前后端代理配置放在同一个server块里管理起来方便。更新后的myapp_frontend.conf完整示例如下server { listen 80; server_name your_domain.com; # 改为你的域名或IP # 前端静态资源 root /home/myapp/frontend; index index.html index.htm; # 前端路由支持 location / { try_files $uri $uri/ /index.html; } # 后端API代理 - 假设你的前端请求以 /api 开头 location /api/ { # 代理到后端SpringBoot应用 proxy_pass http://127.0.0.1:8080/; # 注意结尾的斜杠它会影响URL重写 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_send_timeout 60s; proxy_read_timeout 60s; } # 可选代理WebSocket如果应用用到 # location /ws/ { # proxy_pass http://127.0.0.1:8080; # proxy_http_version 1.1; # proxy_set_header Upgrade $http_upgrade; # proxy_set_header Connection upgrade; # } # 静态资源缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control public, immutable; } }关键点解析location /api/: 这个配置块匹配所有以/api开头的请求。proxy_pass http://127.0.0.1:8080/;: 将这些请求转发到本机8080端口运行的SpringBoot应用。结尾的斜杠非常重要。它意味着/api/user这个请求会被转发为http://127.0.0.1:8080/user。如果没有结尾的斜杠则会转发为http://127.0.0.1:8080/api/user这通常会导致后端接口404。这是新手最容易踩的坑之一。proxy_set_header: 这几行将客户端的真实IP、协议等信息传递给后端应用对于日志记录和某些安全策略非常重要。再次执行sudo nginx -t和sudo systemctl reload nginx使配置生效。现在前端页面中对/api/xxx的请求就会被Nginx正确转发到后端服务了。4.2 将SpringBoot应用配置为系统服务用java -jar 运行应用一旦终端关闭或服务器重启应用就停止了。我们需要将其注册为系统服务实现守护进程、开机自启和集中日志管理。这里我们使用systemd它是现代Linux发行版的标准服务管理工具。创建服务单元文件在/etc/systemd/system/目录下创建一个以.service结尾的文件例如myapp-backend.service。sudo vim /etc/systemd/system/myapp-backend.service编写服务配置将以下内容写入文件请根据你的实际路径修改ExecStart、WorkingDirectory等参数。[Unit] DescriptionMy SpringBoot Backend Application Afternetwork.target syslog.target [Service] Typesimple Userappuser # 建议创建一个非root用户来运行服务这里假设是appuser Groupappuser WorkingDirectory/home/myapp/backend ExecStart/usr/bin/java -Xms256m -Xmx512m -jar myapp-0.0.1-SNAPSHOT.jar # 或者指定配置文件-jar myapp.jar --spring.config.location/home/myapp/backend/application-prod.yml ExecStop/bin/kill -15 $MAINPID Restarton-failure RestartSec10 StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target配置详解User/Group: 使用非root用户运行服务是重要的安全实践。你需要提前创建这个用户sudo useradd -r -s /bin/false appuser并确保该用户对Jar包和日志目录有读写权限。WorkingDirectory: 服务的工作目录应用生成的日志文件等会在这里。ExecStart: 启动命令。-Xms和-Xmx是JVM堆内存参数根据你的应用实际情况调整。Restart: 配置为失败时自动重启提高服务的健壮性。设置权限并启动服务# 重新加载systemd配置 sudo systemctl daemon-reload # 启动服务 sudo systemctl start myapp-backend # 设置开机自启 sudo systemctl enable myapp-backend # 查看服务状态 sudo systemctl status myapp-backend如果状态显示为active (running)恭喜你后端服务已经成功守护进程化了。查看应用日志服务日志由systemd的journal管理可以通过以下命令查看sudo journalctl -u myapp-backend -f # -f 表示实时跟踪日志你也可以在SpringBoot的application.properties或application.yml中配置将日志输出到文件方便管理和切割。至此一个基本的VueSpringBoot前后端分离项目已经在麒麟系统上部署完成。用户通过80端口访问NginxNginx提供前端页面并代理API请求到后端8080端口的SpringBoot服务后端服务以系统服务的形式稳定运行。5. 进阶配置、优化与故障排查基础部署完成后为了生产环境的稳定和高可用我们还需要考虑一些进阶配置和优化点。5.1 使用域名与HTTPS配置如果拥有域名建议配置域名并启用HTTPS这不仅是安全最佳实践也对SEO等有好处。域名解析在域名服务商处将你的域名A记录解析到服务器公网IP。修改Nginx配置将server_name改为你的域名。申请SSL证书可以使用Let‘s Encrypt的免费证书通过Certbot工具自动化申请和续期。# 以基于CentOS系统为例安装Certbot sudo yum install -y certbot python3-certbot-nginx # 运行Certbot它会自动修改你的Nginx配置 sudo certbot --nginx -d your_domain.comCertbot会自动完成证书申请、验证和Nginx配置更新。它会将HTTP请求重定向到HTTPS并配置好证书路径。5.2 前端路由与后端跨域问题在前后端分离架构中有两个经典问题1. 前端路由刷新404这个问题在Vue Router的history模式下会出现。当用户直接访问一个前端路由如/dashboard或刷新页面时Nginx会去root目录下找/dashboard这个文件或目录显然找不到于是返回404。我们在之前的Nginx配置中已经通过try_files $uri $uri/ /index.html;解决了这个问题。它的作用是先尝试找匹配的文件或目录如果都找不到最后返回/index.html由Vue应用内部的路由系统来处理。2. 跨域问题CORS在开发阶段我们经常通过Vue CLI的代理或配置后端允许跨域来解决。在生产环境由于我们使用了Nginx反向代理前端浏览器访问的是同一个域名和端口Nginx的80/443API请求被Nginx转发实际上不存在跨域问题。因此只要Nginx代理配置正确生产环境通常无需额外处理CORS。但是如果你的后端服务还需要被其他非同一域名下的前端直接调用则需要在SpringBoot后端配置CORS。例如在Spring Boot的配置类中添加Configuration public class WebConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) // 允许跨域的路径 .allowedOrigins(https://your-frontend-domain.com) // 允许的源 .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) // 允许的方法 .allowCredentials(true); // 是否允许发送Cookie } }5.3 性能优化与监控1. Nginx优化连接数与缓冲区根据服务器性能和预期并发调整worker_connections,keepalive_timeout,client_max_body_size文件上传大小限制等参数在主配置文件/etc/nginx/nginx.conf中修改。启用Gzip压缩压缩文本资源显著减少传输体积。在Nginx配置中添加或启用gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css text/xml text/javascript application/javascript application/xmlrss application/json;2. SpringBoot JVM优化在systemd服务文件的ExecStart中调整JVM参数是关键。除了堆内存-Xms,-Xmx还可以考虑-XX:UseG1GC使用G1垃圾收集器通常能提供更好的延迟和吞吐量平衡。-XX:MaxGCPauseMillis200设置期望的最大GC停顿时间目标。-Xlog:gc*:file/home/myapp/backend/gc.log:time输出GC日志以便分析。 示例ExecStart/usr/bin/java -Xms512m -Xmx1024m -XX:UseG1GC -XX:MaxGCPauseMillis200 -jar myapp.jar3. 日志管理Nginx日志访问日志和错误日志默认在/var/log/nginx/。可以使用logrotate工具进行日志切割和归档防止日志文件过大。应用日志建议在SpringBoot的application-prod.yml中配置日志输出到文件并按日期或大小滚动。例如使用Logback配置。5.4 常见问题与排查技巧实录部署过程中难免会遇到问题这里记录几个我踩过的坑和排查思路。问题1Nginx启动失败或配置重载失败现象执行sudo systemctl start nginx或sudo nginx -s reload失败。排查首先运行sudo nginx -t检查配置文件语法。它会精确指出哪一行有错误。检查端口占用sudo lsof -i:80或sudo netstat -tlnp | grep :80看80端口是否被其他程序如Apache、另一个Nginx实例占用。检查SELinux如果语法和端口都没问题可能是SELinux阻止了Nginx访问前端目录。可以暂时禁用SELinux测试或使用chcon命令修改目录安全上下文。问题2前端页面能打开但所有API请求都报404或502错误现象浏览器开发者工具中网络请求显示404或502。排查404首先检查Nginx代理配置的proxy_pass地址和路径是否正确。重点检查结尾的斜杠。同时确认后端SpringBoot应用是否真的在运行并监听对应端口sudo systemctl status myapp-backend和sudo lsof -i:8080。502 Bad Gateway这通常意味着Nginx无法连接到后端服务。确认后端服务已启动且监听端口正确。检查防火墙是否开放了8080端口如果是本机转发通常不需要但安全策略严格的服务器可能需要。查看Nginx错误日志sudo tail -f /var/log/nginx/error.log里面通常会有更具体的连接失败原因。问题3后端服务启动失败现象sudo systemctl status myapp-backend显示failed或inactive。排查查看详细日志sudo journalctl -u myapp-backend -n 50 --no-pager查看最近50行日志。错误信息通常会直接显示例如Jar包找不到、端口被占用、数据库连接失败、配置文件错误等。检查文件权限确保运行服务的用户如appuser对Jar包、工作目录以及可能用到的外部配置文件、日志目录有读写和执行权限。检查端口占用sudo lsof -i:8080看8080端口是否已被其他进程占用。内存不足如果JVM申请的内存超过系统可用内存会导致启动失败。检查-Xmx参数设置是否合理以及服务器剩余内存free -h。问题4静态资源JS/CSS/图片加载失败或未更新现象页面样式错乱或修改了前端代码重新构建上传后浏览器看到的还是旧版本。排查浏览器缓存这是最常见的原因。在Nginx配置中我们已经为静态资源设置了长期缓存expires 1y。这意味着浏览器在一年内都不会再向服务器请求这个文件。解决方案在构建前端时使用Webpack等工具的哈希功能让文件名随内容变化如app.abc123.js。这样文件内容一变URL就变了浏览器自然会请求新文件。Vue CLI默认就启用了这个功能。Nginx缓存如果配置了Nginx代理缓存可能需要清理。检查Nginx配置。文件路径错误检查Nginx配置中的root指令路径是否正确以及上传的dist文件是否完整覆盖了旧文件。部署是一个系统工程从环境准备到服务上线每一步都需要仔细核对。尤其是在国产化操作系统上可能会遇到一些依赖库版本、路径差异等特定问题保持耐心善用搜索引擎和日志排查工具大部分问题都能找到解决方案。将上述步骤脚本化、文档化是提升后续部署效率和团队协作能力的好习惯。