前文:部署笔记之将本地的Vue+Spring Boot 前后端分离项目部署到云服务器上(www域名与HTTPS)
安装Java17后导致旧项目Java8无法启动502错误;
服务器2G内存不足导致项目数据库连接总是断连崩溃;

前端请求的接口地址虽然能到达服务器,但后端服务没有正常响应,导致中间的代理( Nginx)返回了 502。
一、检查旧项目的 Systemd 服务配置
1、查看 /etc/systemd/system 目录下的所有 service 文件
bash
ls -l /etc/systemd/system/*.service

简单说:这三文件是我对应三个不同前后端项目的后端在 Linux 上实现 "开机自启、后台运行、故障重启" 的 "管理说明书"。
bash
cat /etc/systemd/system/旧项目.service
可以发现,三个后端使用不同的 Java 版本:
my-springboot-app.service:使用系统默认 Java(/usr/bin/java)
my-project5.service:同样使用系统默认 Java
my-project6.service:明确指定了 Java 17 的绝对路径
原来的 Java 1.8 项目(my-springboot-app.service、my-project5.service)的 ExecStart 用的是 /usr/bin/java,这个路径是系统默认的 Java 可执行文件。当我安装 Java 17 并通过 alternatives 或包管理器更新了默认 Java 版本后,/usr/bin/java 指向的就变成了 Java 17,而不是 Java 1.8。这导致你的旧项目被强制用 Java 17 启动,而它们是用 Java 1.8 编译的,运行时会出现 不兼容错误,所以连接失败。
二、排查 Systemd 服务的Java配置
1、Java安装路径
找到 Java 1.8 的绝对路径
执行:
bash
ls /usr/lib/jvm/
提供的/usr/lib/jvm/列表里,Java 1.8 的完整路径是:

bash
vim /etc/systemd/system/my-xxx.service
- my-springboot-app.service
bash
vim /etc/systemd/system/my-springboot-app.service
把ExecStart改成:
bash
ExecStart=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.462.b08-2.0.1.1.al8.x86_64/bin/java -jar /www/my-project/backend/jjZy-0.0.1-SNAPSHOT.jar
- my-project5.service
bash
vim /etc/systemd/system/my-project5.service
把ExecStart改成:
bash
ExecStart=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.462.b08-2.0.1.1.al8.x86_64/bin/java -jar /www/my-project5/backend/official_website-0.0.1-SNAPSHOT.jar
改完后执行:
bash
systemctl daemon-reload
systemctl restart my-springboot-app my-project5
2、后端刚启动就又要重启
服务状态是 Active: active (running),但刚启动就又要重启,CTRL+C退出。

说明:
- 服务启动后很快就退出(可能是崩溃或主动退出)
- 因为在 .service 里配置了:
bash
Restart=always
RestartSec=5
所以 systemd 会在 5 秒后重新启动它
- 这种 "启动 → 退出 → 重启" 的循环,就会导致前端访问时出现 502 Bad Gateway(因为后端服务还没准备好,或者已经挂掉)
三、排查后端服务
1、后端服务日志
直接查看配置的日志文件(最直接):

在 my-springboot-app.service 里已经指定了日志输出到项目目录,直接用 tail 命令查看:
bash
# 查看普通输出日志(启动过程、业务日志)
tail -f /www/my-project/backend/app.log
# 查看错误日志(启动失败、异常报错)
tail -f /www/my-project/backend/error.log
输入:tail -f /www/my-project/backend/app.log后发现,

意思是我的 Spring Boot 项目启动时,尝试连接 MySQL 数据库但连不上,具体原因是 Connection refused(连接被拒绝)。
我的 MySQL 是运行在 Docker 容器 中的,启动方式是:
bash
docker exec -it mysql8 mysql -uroot -p

我的 MySQL 容器(名字是 mysql8)现在没在运行,所以没法进入容器操作。
先启动 MySQL 容器:
bash
docker start mysql8
启动后再进入容器:
bash
docker exec -it mysql8 mysql -uroot -p

诶???我三个后端的数据库呢???
2、上传数据库
现在的问题是SQL 文件没有复制到 MySQL 容器:
bash
# 先启动 MySQL 容器
docker start mysql8
# 进入 MySQL 容器(mysql8 是容器名)
docker exec -it mysql8 bash
# 查看 /tmp 目录
ls -l /tmp

这个容器的/tmp目录是空的,没有任何文件(包括之前后端所有复制的xxx.sql都没了,重新复制一下)。
输入:exit退出容器的交互模式回到宿主机。
(1)第一个后端项目
bash
ls -l /www/my-project/backend
上传 SQL 文件到服务器:

查看application.yml的内容,确认数据库名:
bash
cat /www/my-project/backend/application.yml

服务器端创建数据库 + 导入 SQL(解决 Docker 容器路径隔离问题):
bash
# 1. 先复制SQL文件到MySQL容器的 /tmp 目录(容器无法直接访问宿主机路径)
docker cp /www/my-project/backend/zy.sql mysql8:/tmp/zy.sql
# 2. 进入MySQL容器,创建数据库并导入
docker exec -it mysql8 mysql -uroot -p
# 输入MySQL密码后执行以下命令:
CREATE DATABASE 你的数据库名 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 强制utf8mb4,兼容emoji
USE 你的数据库名;
SOURCE /tmp/xxx.sql; # 导入容器内的SQL文件(核心:路径是容器内的/tmp)
SHOW TABLES; # 验证表是否导入成功
exit; # 退出MySQL
# 3. 可选:删除容器内临时SQL文件(节省空间)
docker exec -it mysql8 rm /tmp/xxx.sql
nice,连上了!

(2)第二个后端项目
bash
ls -l /www/my-project5/backend
上传 SQL 文件到服务器:

查看application.yml的内容,确认数据库名:
bash
cat /www/my-project5/backend/application.yml

服务器端创建数据库 + 导入 SQL(解决 Docker 容器路径隔离问题):
bash
# 1. 先复制SQL文件到MySQL容器的 /tmp 目录(容器无法直接访问宿主机路径)
docker cp /www/my-project5/backend/official_website.sql mysql8:/tmp/official_website.sql
# 2. 进入MySQL容器,创建数据库并导入
docker exec -it mysql8 mysql -uroot -p
# 输入MySQL密码后执行以下命令:
CREATE DATABASE 你的数据库名 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 强制utf8mb4,兼容emoji
USE 你的数据库名;
SOURCE /tmp/xxx.sql; # 导入容器内的SQL文件(核心:路径是容器内的/tmp)
SHOW TABLES; # 验证表是否导入成功
exit; # 退出MySQL
# 3. 可选:删除容器内临时SQL文件(节省空间)
docker exec -it mysql8 rm /tmp/xxx.sql
nice,连上了!

(3)第三个后端项目
bash
ls -l /www/my-project6/backend
上传 SQL 文件到服务器:

Windows 上传 SQL 文件到 MySQL 容器:
bash
scp /本地路径/xxx.sql root@服务器IP:/www/my-project6/backend/

查看application.yml的内容,确认数据库名:
bash
cat /www/my-project6/backend/application.yml

服务器端创建数据库 + 导入 SQL(解决 Docker 容器路径隔离问题):
bash
# 1. 先复制SQL文件到MySQL容器的 /tmp 目录(容器无法直接访问宿主机路径)
docker cp /www/my-project6/backend/linkdin.sql mysql8:/tmp/linkdin.sql
# 2. 进入MySQL容器,创建数据库并导入
docker exec -it mysql8 mysql -uroot -p
# 输入MySQL密码后执行以下命令:
CREATE DATABASE 你的数据库名 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 强制utf8mb4,兼容emoji
USE 你的数据库名;
SOURCE /tmp/xxx.sql; # 导入容器内的SQL文件(核心:路径是容器内的/tmp)
SHOW TABLES; # 验证表是否导入成功
exit; # 退出MySQL
# 3. 可选:删除容器内临时SQL文件(节省空间)
docker exec -it mysql8 rm /tmp/xxx.sql

nice,连上了!

四、容器内存不足
Exited (137):表示容器已经退出,退出码137通常是因为容器被强制杀死(比如内存不足、系统 OOM),这就是容器停掉、连不上的直接原因。

mysql8容器因为内存不够(或资源耗尽)崩溃退出了。。。2核2G还不够吗
1、看内存占用,腾资源
在宿主机执行,看看谁占了内存:
bash
top # 按M键按内存排序
2 核 2G 服务器里,java进程占了近 22% 的内存,再加上其他服务,留给 MySQL 容器的内存不够,这才导致 MySQL 容器因内存不足崩溃(退出码 137)。

bash
# 找到java进程的PID(比如1361001)
ps -ef | grep java
# 临时停止(之后需要的话再启动)
kill -9 [java的PID]

这 3 个 Java 进程已经会吃掉不少内存了,加上之前的 Redis、MySQL 容器,2 核 2G 的服务器资源肯定不够用 ------ 这也是 MySQL 总崩溃的直接原因。
bash
# 停掉第一个Java进程(PID是178407,杀不死因为设置systemd 会在 5 秒后重新启动它,升级你的服务器吧!)
kill -9 178407
2、升级云服务器
这两个 Java 进程会占用大量内存(之前top里看到java占了 22% 内存),加上 Redis、MySQL 容器等服务,直接把 2G 内存吃光了 ------ 这就是 MySQL 容器崩溃的核心原因。(Java 本身是 "内存大户",单个 Spring Boot 项目启动至少要 200-500M 内存)

啊这。。。系统盘也升级要手动扩容啊,数据盘不涉及还好。