记一次 Druid 连接 MySQL 报 Communications link failure 的排查过程

问题现象

Druid 连接池启动时报错:

复制代码
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.
    at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:361)
    ...
Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol 
(protocol is disabled or cipher suites are in

连接地址是 jdbc:mysql://127.0.0.1:3306/k_k,MySQL 就在本机。

排查过程

1. 先排除基础问题

确认 MySQL 服务在运行、端口 3306 可通,排除服务没启动、防火墙拦截等常见原因。

2. 定位到 SSL 握手阶段

堆栈里最关键的一行是:

复制代码
at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:361)

说明 TCP 连接已经建立,问题出在 SSL 握手阶段,而不是网络不通。

3. 检查 MySQL 的 TLS 配置

sql 复制代码
SHOW VARIABLES LIKE 'tls_version';

结果:

复制代码
TLSv1,TLSv1.1,TLSv1.2

MySQL 支持 TLSv1.2,但同时也启用了已被淘汰的 TLSv1 和 TLSv1.1。

4. 获取 CA 证书

MySQL 启用 SSL 后,数据目录下会生成一组证书文件。先找到数据目录:

sql 复制代码
SHOW VARIABLES LIKE 'datadir';

在数据目录里找到 ca.pem,这就是服务端的 CA 证书。

5. 将 CA 证书导入 Java 信任库

使用 JDK 自带的 keytool:

bash 复制代码
/www/server/java/jdk1.8.0_371/bin/keytool -importcert \
  -alias MySQLCACert \
  -file /www/server/data/ca.pem \
  -keystore truststore.jks \
  -storepass 你的密码

生成的 truststore.jks 位于执行命令时的当前目录。

6. 在 JDBC URL 中配置信任库

复制代码
jdbc:mysql://127.0.0.1:3306/k_k?sslMode=VERIFY_CA&trustCertificateKeyStoreUrl=file:/路径/truststore.jks&trustCertificateKeyStorePassword=你的密码

重新启动后,仍然报同样的错。

真正的原因

这是 MySQL Connector/J 8.0.18 及更早版本的一个已知设计问题:

  • Connector/J 8.0.16 出于兼容旧版 MySQL(yaSSL 编译)的考虑,默认不启用 TLSv1.2,只尝试用 TLSv1/TLSv1.1 协商。
  • JDK 8u371 默认禁用了 TLSv1 和 TLSv1.1 这两个不安全的旧协议。

双方在"能用哪个协议"上谈不拢,SSL 握手直接失败。

解决方案

在 JDBC URL 中显式指定 TLS 协议版本:

复制代码
jdbc:mysql://127.0.0.1:3306/k_k?sslMode=VERIFY_CA&trustCertificateKeyStoreUrl=file:/路径/truststore.jks&trustCertificateKeyStorePassword=你的密码&enabledTLSProtocols=TLSv1.2

关键是 enabledTLSProtocols=TLSv1.2,它强制驱动使用 TLSv1.2,打破协议僵局。加上后连接正常。

几个容易踩的坑

  • ssl_cipher 查询为空是正常的,MySQL 8.0 的密码套件由底层 OpenSSL 管理,不再通过该变量显式列出。
  • ssl_ca 只返回 ca.pem 而非完整路径也是正常的 ,该变量存储的是配置文件里填写的值,要拿绝对路径得查 datadir。
  • keytool 命令找不到 ,是因为它不在系统 PATH 里,需要用 JDK bin 目录下的绝对路径执行。

后续可以改进的地方

  1. 升级驱动 :Connector/J 8.0.19 及以上版本已修复默认不启用 TLSv1.2 的问题,升级后可以去掉 enabledTLSProtocols 参数。
  2. 清理 MySQL 旧协议 :在 my.cnf 的 [mysqld] 段加上 tls_version=TLSv1.2,TLSv1.3,重启 MySQL,让服务端也彻底禁用旧协议,安全性更好。

最终可用配置

复制代码
jdbc:mysql://127.0.0.1:3306/k_k?sslMode=VERIFY_CA&trustCertificateKeyStoreUrl=file:/路径/truststore.jks&trustCertificateKeyStorePassword=你的密码&enabledTLSProtocols=TLSv1.2

版本信息:

  • MySQL Connector/J 8.0.16
  • Druid 1.1.18
  • JDK 1.8.0_371
复制代码
相关推荐
自强的小白1 小时前
mybatis_plus的核心功能(条件构造器)
mysql
adinnet20262 小时前
多轮对话与上下文压缩:追问时模型怎么记住前面说的
数据库·microsoft
JosieBook2 小时前
【数据库】MySQL 实战精通系列 · 第11篇:Redis 缓存与 MySQL 一致性实战
数据库·mysql·缓存
Leo.yuan3 小时前
2026企业级数据集成平台市场报告:国内外厂商格局与技术路线
数据库·oracle
guo_wen_qiang3 小时前
云服务器mysql分库分表环境搭建(2库4表)
数据库·mysql·docker
jianpeng的工程笔记3 小时前
EL8 / EL9 安装 Slurm 26.05.4:主备控制器、MariaDB 记账与作业验收
linux·数据库·mariadb·高性能计算·slurm
SelectDB技术团队3 小时前
ClickHouse 存日志的能力边界:并发、检索与 trace 回放的实测对照
数据结构·数据库·clickhouse·日志分析·apache doris·日志存储
倔强的小石头_3 小时前
Ubuntu部署Prometheus与Alertmanager:systemd配置、告警对接及cpolar远程访问
数据库·ubuntu·prometheus
茉莉玫瑰花茶4 小时前
GO [ 接口 ]
服务器·数据库·golang