前几天发现一直跑的项目本地无法启动了:
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.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-java-8.0.17.jar:8.0.17]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-java-8.0.17.jar:8.0.17]
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:827) ~[mysql-connector-java-8.0.17.jar:8.0.17]
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:447) ~[mysql-connector-java-8.0.17.jar:8.0.17]
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:237) ~[mysql-connector-java-8.0.17.jar:8.0.17]
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199) ~[mysql-connector-java-8.0.17.jar:8.0.17]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:136) ~[HikariCP-3.2.0.jar:na]
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:369) ~[HikariCP-3.2.0.jar:na]
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:198) ~[HikariCP-3.2.0.jar:na]
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:467) [HikariCP-3.2.0.jar:na]
at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:541) [HikariCP-3.2.0.jar:na]
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115) [HikariCP-3.2.0.jar:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) [HikariCP-3.2.0.jar:na]
at com.zaxxer.hikari.HikariDataSource$$FastClassBySpringCGLIB$$eeb1ae86.invoke(<generated>) [HikariCP-3.2.0.jar:na]
复制代码
看到Communications link failure
初步认为是超时了,网络问题导致的,但在解决了网络问题后发现依旧报相同的错,这就奇怪了,然后一条一条的看报错日志,找到:
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:171) ~[na:1.8.0_292]
at sun.security.ssl.ClientHandshakeContext.<init>(ClientHandshakeContext.java:98) ~[na:1.8.0_292]
at sun.security.ssl.TransportContext.kickstart(TransportContext.java:220) ~[na:1.8.0_292]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:428) ~[na:1.8.0_292]
at com.mysql.cj.protocol.ExportControlled.performTlsHandshake(ExportControlled.java:316) ~[mysql-connector-java-8.0.17.jar:8.0.17]
at com.mysql.cj.protocol.StandardSocketFactory.performTlsHandshake(StandardSocketFactory.java:188) ~[mysql-connector-java-8.0.17.jar:8.0.17]
at com.mysql.cj.protocol.a.NativeSocketConnection.performTlsHandshake(NativeSocketConnection.java:99) ~[mysql-connector-java-8.0.17.jar:8.0.17]
at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:331) ~[mysql-connector-java-8.0.17.jar:8.0.17]
... 68 common frames omitted
复制代码
看到SSLHandshakeException
,心里打起了问号?这个错误比较反常,最终网上找了一番,问题定位了:
JDK 8高版本导致的,之前用的
1.8.0_281
,前些天捣鼓Homebrew,发现JDK 8有新版本,就升级了1.8.0_292
,然后发现项目无法启动了。
查看/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/lib/security/java.security
(Mac上;Windows同理,在jre/lib/security/java.security
里面)发现:
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
include jdk.disabled.namedCurves
复制代码
-
方法一:
此处连接的MySQL,导致的报错,修改jdbcUrl,在其后面加
useSSL=false
后运行正常 -
方法二:
删除
SSLv3, TLSv1, TLSv1.1
并保存java.security
文件,重启项目即可解决问题,删除后此处为:# Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 jdk.tls.disabledAlgorithms=RC4, DES, MD5withRSA, \ DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ include jdk.disabled.namedCurves 复制代码
-
方法三:
降低JDK版本,这个相当也容易操作,比如可以从
1.8.0_292
降到1.8.0_281
,甚至是1.8.0_275
版本,但个人不建议,因为Oracle对JDK 8的支持一直会到2030年:
即使很长一段时间用JDK 8,但JDK 8本身也是有小版本迭代的,比如你明年换了电脑,安装JDK,基本是1.8.0_292
之后的版本,那这个问题会一直存在
-
方法四:
方法一 能解决由SSL调用权限导致的所有问题,但破坏了安全性
方法二 针对MySQL的问题,可以快速解决
方法三 不推荐因此,碰到类似问题,基本的思路是兼容
JDK 8高版本
甚至JDK高版本
,比如代码层面的:private Socket overrideTlsProtocol(final Socket socket) { if (!(socket instanceof SSLSocket)) { throw new RuntimeException("Error, an instance of SSLSocket is expected"); } ((SSLSocket) socket).setEnabledProtocols(new String[]{"SSLv3"}); return socket; } 复制代码
修改为:
private Socket overrideTlsProtocol(final Socket socket) { if (!(socket instanceof SSLSocket)) { throw new RuntimeException("Error, an instance of SSLSocket is expected"); } ((SSLSocket) socket).setEnabledProtocols(new String[]{"SSLv3", "TLSv1","TLSv1.1"}); return socket; } 复制代码
有问题直面问题、解决问题,不要拍折腾,经常捣鼓这些东西,相信你也会受益匪浅,希望对你有所帮助~😄😄😄
近期评论