记一次 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
复制代码
相关推荐
zyseo85 小时前
谷歌SEO 准首页词挖掘脚本:找出排在第 8-20 名的隐藏流量
大数据·数据库·人工智能
xiaogai_gai7 小时前
仅查询策略实战:从金蝶云·星空旗舰版定时拉取收料通知单
大数据·数据库·python
数据工匠老o7 小时前
异构数据库DDL同步:260条链路的结构变更自动适配方案
数据库·架构
L0017 小时前
MySQL5.7 DATE 字段无法设置默认日期?用触发器搞定|个人任务清单项目实战
mysql
这个DBA有点耶8 小时前
银行业市占率最高的国产数据库是谁?先搞清楚“市占率”的四种口径
数据库·程序员·架构
用户6279947182629 小时前
南大通用GBase 8a之基于审计日志的冷温热数据分析
数据库
数据库小学妹9 小时前
数据库运维五级成熟度:监控、备份、高可用怎么串起来
运维·数据库·监控
一个天蝎座的程序猿9 小时前
为了给报表提速,我把金仓KES的列存储折腾了个遍:聊聊KES的技术能力
数据库
飞越未来云城的霓虹飞猪9 小时前
AI 数据库地图:从 PostgreSQL 到向量数据库,一次看懂 AI 时代的数据底座
数据库
不像程序员的程序媛9 小时前
导出mysql数据结构
数据库·mysql