当在docker容器中实现Java应用程序时,以及在自己的docker容器中配置的MySQL数据库与Docker组合一起实现时,在使用jdbc创建到数据库的连接时,总是会发生以下错误:
currency_server_v0_1 | com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
currency_server_v0_1 |
currency_server_v0_1 | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
currency_server_v0_1 | at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
currency_server_v0_1 | at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
currency_server_v0_1 | at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836)
currency_server_v0_1 | at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456)
currency_server_v0_1 | at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246)
currency_server_v0_1 | at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:197)
currency_server_v0_1 | at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
currency_server_v0_1 | at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)
currency_server_v0_1 | at Test.main(Test.java:22)
currency_server_v0_1 | Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
currency_server_v0_1 |
currency_server_v0_1 | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
currency_server_v0_1 | at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
currency_server_v0_1 | at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:78)
currency_server_v0_1 | at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
currency_server_v0_1 | at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
currency_server_v0_1 | at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
currency_server_v0_1 | at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
currency_server_v0_1 | at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105)
currency_server_v0_1 | at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151)
currency_server_v0_1 | at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167)
currency_server_v0_1 | at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:91)
currency_server_v0_1 | at com.mysql.cj.NativeSession.connect(NativeSession.java:144)
currency_server_v0_1 | at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:956)
currency_server_v0_1 | at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:826)
currency_server_v0_1 | ... 6 more
currency_server_v0_1 | Caused by: java.net.ConnectException: Connection refused
currency_server_v0_1 | at java.base/sun.nio.ch.Net.connect0(Native Method)
currency_server_v0_1 | at java.base/sun.nio.ch.Net.connect(Net.java:576)
currency_server_v0_1 | at java.base/sun.nio.ch.Net.connect(Net.java:565)
currency_server_v0_1 | at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:588)
currency_server_v0_1 | at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:333)
currency_server_v0_1 | at java.base/java.net.Socket.connect(Socket.java:645)
currency_server_v0_1 | at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:155)
currency_server_v0_1 | at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:65)
currency_server_v0_1 | ... 9 more
currency_server_v0_currency_server_v0_1 exited with code 0相应的Docker文件和Java代码如下所示: docker-compose.yml: version:"3.7“
services:
currency_server_v0:
build: .
ports:
- 8080:8080
depends_on:
- mysqldb
networks:
currency-mysql:
mysqldb:
image: mysql:5.7
container_name: mysqldb
ports:
- 3306:3306
networks:
currency-mysql:
volumes:
- db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=currency_server_db
- MYSQL_USER= admin
- MYSQL_PASSWORD= admin
volumes:
db:
networks:
currency-mysql:Java中的JDBC连接:
try (Connection conn = DriverManager.getConnection(
"jdbc:mysql://mysqldb:3306/currency_server_db", "root", "root");
Statement stmt = conn.createStatement();
) {
String sql = "CREATE TABLE TEST " +
"(id INTEGER not NULL, " +
" PRIMARY KEY ( id ))";
stmt.executeUpdate(sql);
System.out.println("Created table in given database...");
} catch (SQLException e) {
e.printStackTrace();
}Dockerfile:
FROM openjdk:16-alpine3.13
COPY target/currency_server_v0-1.0-SNAPSHOT-jar-with-dependencies.jar app.jar
ENTRYPOINT ["java","-jar", "app.jar"]有人有或知道这个问题吗?谢谢你的回答。
发布于 2022-04-27 17:20:16
您的服务启动速度比MySql快,尽管depends_on不知道如何检查容器是否准备好接受连接。您可以在服务Dockerfile中实现等待行为,也可以在Java中这样做:
public static void main(final String[] args) {
waitForServer("mysqldb", 3306, 10_000);
}
public static void waitForServer(String host, int port, int timeout) {
long start = System.currentTimeMillis();
while (portUnavailable(host, port)) {
System.out.println("Waiting for port to open: " + port);
if (System.currentTimeMillis() - start > timeout) {
throw new Error("Timeout waiting for port to open: " + port);
}
}
}
private static boolean portUnavailable(String host, int port) {
try (Socket s = new Socket(host, port)) {
return false;
} catch (Exception e) {
return true;
}
}https://stackoverflow.com/questions/72030685
复制相似问题