目录
一、问题背景
二、典型错误日志
三、第一反应:常规排查(但都没用)
1️⃣ 数据库是否存活
2️⃣ 网络是否连通
3️⃣ 配置是否正确
4️⃣ Java 服务是否真的跑在目标服务器
四、真正的原因:JVM 默认使用 IPv6,而 MySQL 只监听 IPv4
🔥 真正的根因其实在这里:
发生了什么?
为什么 mysql 命令行没问题?
五、最终解决方案(关键一步)
✅ 强制 JVM 使用 IPv4
六、为什么这个问题特别“迷惑新人”
七、这个问题的“识别特征”(以后看到就秒懂)
八、推荐的生产级 Java 启动模板
九、总结
一、问题背景
在服务器上部署 Java 后端服务时,遇到了一个非常诡异但又极其常见的问题:
✅ 在服务器上使用
mysql命令行可以正常连接数据库❌ Java 后端程序启动后,所有涉及数据库的接口全部失败
❌ 登录接口直接报错,页面无法跳转
❌ 日志中反复出现:
Communications link failure The last packet sent successfully to the server was 0 milliseconds ago Connection refused一开始几乎把所有常规排查方向都检查了一遍,但问题依旧存在。
二、典型错误日志
核心异常如下(节选):
Caused by: com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. Caused by: java.net.ConnectException: Connection refused出错位置在 MyBatis 查询阶段,例如:
UserMapper.selectByUsername三、第一反应:常规排查(但都没用)
当时依次排查了下面这些点:
1️⃣ 数据库是否存活
systemctl status mysqld✅ 正常
2️⃣ 网络是否连通
mysql -h 192.168.8.101 -u ivos -p✅ 可以成功进入 MySQL
3️⃣ 配置是否正确
spring.datasource.url=jdbc:mysql://192.168.8.101:3306/ivos spring.datasource.username=ivos spring.datasource.password=******✅ IP、端口、库名、账号都没问题
4️⃣ Java 服务是否真的跑在目标服务器
ps -ef | grep java ss -antulp | grep 8080✅ Java 服务确实运行在javaserver上
👉到这里就开始迷惑了:
明明服务器能连数据库,
明明 Java 就在这台服务器上,
为什么程序死活连不上?
四、真正的原因:JVM 默认使用 IPv6,而 MySQL 只监听 IPv4
🔥 真正的根因其实在这里:
mysql 命令行 ≠ Java 程序
它们走的是完全不同的网络栈
发生了什么?
MySQL 实际监听的是 IPv4:
0.0.0.0:3306Java(JDK 8 + MySQL Connector/J 8.x)在 Linux 上:
默认优先使用 IPv6
即使你写的是 IPv4 地址(如
192.168.8.101)
结果是:
JVM 尝试用 IPv6 连接 MySQL
MySQL 没监听 IPv6
TCP 连接在第一步就被拒绝
抛出
Connection refused
为什么 mysql 命令行没问题?
因为:
mysql客户端默认走 IPv4不受 JVM 网络策略影响
五、最终解决方案(关键一步)
✅ 强制 JVM 使用 IPv4
停止原有 Java 进程后,用下面方式启动:
nohup java -Djava.net.preferIPv4Stack=true \ -jar ivos-0.0.1-SNAPSHOT.jar \ > ivos.log 2>&1 &启动后:
登录接口恢复正常
所有数据库操作全部成功
问题彻底解决 🎉
六、为什么这个问题特别“迷惑新人”
因为你已经做了所有“看起来正确”的验证:
| 验证方式 | 实际验证的内容 |
|---|---|
| mysql 能连 | 操作系统 IPv4 网络 |
| 账号密码正确 | MySQL 权限 |
| Java 在服务器 | 进程位置 |
| 端口监听正常 | Web 服务 |
👉但没有一个验证 JVM 的网络栈行为
七、这个问题的“识别特征”(以后看到就秒懂)
如果你遇到下面组合,直接优先怀疑 IPv6:
✅ mysql 命令行能连
❌ Java JDBC 连不上
❌ 报
Communications link failure❌
last packet sent 0 ms❌
Connection refusedMySQL 8.x + Connector/J 8.x
八、推荐的生产级 Java 启动模板
以后部署 Java 服务,直接用这个模板:
JAVA_OPTS=" -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 " nohup java $JAVA_OPTS -jar app.jar > app.log 2>&1 &这是大量生产环境的通用写法。
九、总结
这次问题的本质不是配置错误,也不是代码 Bug,而是一个运行环境差异问题:
程序 ≠ 人
程序要遵守 JVM、操作系统和网络栈的规则