java - 连接到 MySQL 的 Java 异常
问题描述
已解决 MySQL JDBC 驱动程序的最新版本显然试图创建 SSL 连接。工作的应用程序没有定义 javax.net.ssl.keystore (和其他)值,所以(我假设)它恢复到非 SSL 连接。失败的应用程序确实定义了所有密钥库/证书参数,然后连接尝试失败 - 仍然不确定确切原因,如果有人能启发会感激。抛出的异常也可能提供更多信息。
无论如何,将“&useSSL=false&allowPublicKeyRetrieval=true”添加到连接参数对这两个应用程序都有效。(虽然对于任何生产应用程序来说都不是一个很好的设置,但可以用于这个 POC!)
============= 原帖如下=========
这让我难过了几天!AWS 服务器 (86_64)、Fedora 29、Java 8 (1.8.0_201-b09)、MySQL - 全部升级到最新版本。MySQL 在同一台服务器上运行。驱动:com.mysql.cj.jdbc.Driver
连接参数:jdbc:mysql://172.31.10.222:3306?user=xxxx&password=xxxx。(IP 是此服务器的 AWS 私有 IP。)
有 2 个不同的实用程序 - 单独的“主要”例程,但都在同一个 JAR 文件中。第一个完美运行,第二个中止并粘贴在下面的堆栈。这在数十次试验中是一致的,但有微小的变化。
不同的主例程都使用堆栈跟踪中显示的“connectToDB”方法。对此进行检测以记录两种情况下驱动程序的所有参数和类名,并验证它们是否相同。
已经尝试/验证:
- 多次谷歌搜索相同的错误
- MySql 正在运行并且正常(通过另一个终端窗口连接没有问题),
- 与所有本地代码一起使用的相同 JAR
- 类路径相同
- 在相同的 Linux 用户下运行,使用相同的 MySQL 用户/密码
- 验证了上面的IP(172.31.10.222)
- 还将 IP 更改为“localhost”、127.0.0.1 和 /etc/hosts 中的符号名称
- 添加 -Xmx2G 以确保不是 OOM 问题
这些是 2 种不同的“主要”方法,但在尝试连接到数据库之前,除了加载一些属性(来自相同的属性文件)之外,别无其他。然后他们执行相同的 connectToDB 例程。
上下文中的某些东西必须有所不同!希望这里的人至少可以提供一些关于在哪里看的提示!
谢谢
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)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:835)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:455)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:240)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:207)
at spc.tools.spcConnection.connectToDB(spcConnection.java:692)
at spc.tools.spcConnection.connectToLocalDB(spcConnection.java:1418)
at spc.tools.spcConnection.loadAllConnectionsOK(spcConnection.java:1112)
at spc.tools.spcConnection.initOneTime(spcConnection.java:1012)
at spc.tools.spcConnection.init(spcConnection.java:194)
at spc.ops.spcServerBase.environmentOK(spcServerBase.java:367)
at spc.ops.spcServerBase.environmentOK(spcServerBase.java:342)
at spc.run.daemon.spcDaemon.main(spcDaemon.java:1082)
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: 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 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151)
at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167)
at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:351)
at com.mysql.cj.protocol.a.NativeAuthenticationProvider.negotiateSSLConnection(NativeAuthenticationProvider.java:777)
at com.mysql.cj.protocol.a.NativeAuthenticationProvider.proceedHandshakeWithPluggableAuthentication(NativeAuthenticationProvider.java:486)
at com.mysql.cj.protocol.a.NativeAuthenticationProvider.connect(NativeAuthenticationProvider.java:202)
at com.mysql.cj.protocol.a.NativeProtocol.connect(NativeProtocol.java:1442)
at com.mysql.cj.NativeSession.connect(NativeSession.java:165)
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:955)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:825)
... 11 more
Caused by: java.net.SocketException: Broken pipe (Write failed)
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
at sun.security.ssl.OutputRecord.writeBuffer(OutputRecord.java:431)
at sun.security.ssl.OutputRecord.write(OutputRecord.java:417)
at sun.security.ssl.SSLSocketImpl.writeRecordInternal(SSLSocketImpl.java:879)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:850)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:720)
at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:1144)
at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:1280)
at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1190)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:369)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
at com.mysql.cj.protocol.ExportControlled.performTlsHandshake(ExportControlled.java:315)
==================================================== ==== 新信息 =====
以下是 connectToDB 方法的关键行(回复下面的评论):
Driver dvr = (Driver)Class.forName(info.sDBDriver).newInstance();
if(dvr!=null) conn = dvr.connect(accessString(), null);
验证了预期的驱动程序,并且 accessString() 返回了 'jdbc:mysql:...' 字符串,如上。执行上面的第二行会引发异常。
从原始帖子开始,在这些行之前输入代码以运行“netstat -ln”并将结果发布到日志中。这显示了端口 3306 的活动侦听器。
解决方案
如果您可以发布 connectToDB() 方法,那就太好了。
根据这句话“第一个完美运行,第二个中止并粘贴在下面的堆栈。”,您必须在第一个 connectToDB() 调用中关闭了数据库连接。
因此,由于第一次调用终止了数据库连接,因此第二次调用被中断。
设置的好方法是对数据库对象使用依赖注入。
希望这可以帮助!
推荐阅读
- python - 如何对直方图的某些特定 bin 进行某种操作?
- responsive - 问题是关于移动浏览器中的响应式网站
- javascript - 如何从“getElementByID”更改为“getElementsByClassName”
- python-3.x - 将 Dict 附加到每个请求的嵌套列表
- axios - Strapi $AND 查询过滤器返回使用 $OR 过滤的值
- bash - 从 Chrome OS 上的终端触发通知
- python - background_task.py 不显示消息 - Python
- html - 如何删除html div元素之间的间距?
- c++ - 使用特殊字符获取正确长度的字符串
- c++ - 如何将原始字符串文字传递给 [[deprecated(message)]] 属性?