部署笔记之部署不同Java版本项目以及多项目内存崩溃问题

前文:部署笔记之将本地的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
  1. 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
  1. 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 内存)

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

相关推荐
麻雀无能为力2 小时前
Diffusion Model(DDPM)学习笔记
笔记·学习
Chloeis Syntax2 小时前
MySQL初阶学习日记(7)--- 事务
java·数据库·笔记·学习·mysql
De-Alf2 小时前
Megatron-LM学习笔记(7)Megatron Model MLP和MoE和EP
笔记·学习
受之以蒙2 小时前
用Rust + dora-rs + Webots打造自动驾驶仿真系统:Mac M1完整实战
人工智能·笔记·rust
紫罗兰盛开2 小时前
python学习笔记
笔记·学习
AI视觉网奇2 小时前
ue 动作 动画学习笔记
笔记·ue5
走在路上的菜鸟2 小时前
Android学Dart学习笔记第二十七节 异步编程
android·笔记·学习·flutter
蒙奇D索大2 小时前
【数据结构】排序算法精讲 | 快速排序全解:高效实现、性能评估、实战剖析
数据结构·笔记·学习·考研·算法·排序算法·改行学it
断剑zou天涯2 小时前
【算法笔记】有序表——AVL树
笔记·算法