[英]JDBCConnectionException: Unable to acquire JDBC Connection when using JPA
[英]Unable to acquire JDBC Connection on integration test when using Docker bridge network
當我在本地運行maven test
通過。 但是當我在CI服務器上運行時出現此錯誤。
Error Message
Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Stacktrace
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
Caused by: com.mysql.jdbc.exceptions.jdbc4.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.
Caused by: java.net.UnknownHostException: mysql
當運行本地測試時,它們全部通過,使用IntelliJ IDEA提供的maven測試默認設置。
由於錯誤抱怨數據庫連接,所以我通過Jenkins Audit檢查了數據庫插件。 連接成功!
我的application.properties
的連接參數也對應於此
spring.datasource.url=jdbc:mysql://mysql:3306/database?useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.maxActive=5
URL中的MySQL是MySQL docker容器名稱。 如果在docker container inspect mysql
使用localhost
或私有IP更改它,則docker container inspect mysql
的錯誤消息是相同的,而Stacktrace在最后兩行有點不同。
對於localhost
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Caused by: java.net.ConnectException: Connection refused (Connection refused)
對於私人IP
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Caused by: java.net.SocketTimeoutException: connect timed out
我認為不同的是URL中的主機,localhost用於本地測試。 而Jenkins服務器則使用Docker橋接網絡。
容器狀態是:
docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
51ea7c7864a4 mysql:5.7 "docker-entrypoint.s…" 19 hours ago Up 19 hours 0.0.0.0:3306->3306/tcp mysql
de364f7b5eaf maven:3-jdk-8 "/usr/local/bin/mvn-…" 21 hours ago Up 21 hours
optimistic_stallman
a6545591e358 jenkinsci/blueocean "/sbin/tini -- /usr/…" 43 hours ago Up 43 hours 0.0.0.0:50000->50000/tcp, 0.0.0.0:2048->8080/tcp frosty_cray
當我在IntelliJ中運行JUnit測試時,它有時會在本地環境中失敗。 錯誤日志如下:
Caused by: org.h2.jdbc.JdbcSQLException: Schema "DATABASE" not found; SQL statement:
TRUNCATE TABLE database.data_log
我已經搜索了這個問題,據說默認情況下h2數據庫使用大寫。 運行maven test
,如果再次在IDE中運行JUnit測試,則會出現此問題。 但這應該與根本原因無關。
搜索錯誤消息,找到一些類似的問題但具有不同的嵌套異常:
無法打開JPA EntityManager進行交易; 嵌套異常是javax.persistence.PersistenceException
SpingREST:無法打開JPA EntityManager進行事務處理; 嵌套異常是org.hiberna
無法打開JPA EntityManager進行交易; org.hibernate.exception.GenericJDBCException:無法打開連接
所有這些都是關於nested exception is javax.persistence.PersistenceException
但是nested exception is org.hibernate.exception.JDBCConnectionException:
是我的情況。 閱讀將Java連接到MySQL數據庫
但是因為該插件連接正常,意味着從Jenkins容器到MySQL容器的連接很好。
總結:
1. maven的本地測試通過
2. Jenkins插件連接MySQL成功
3.從Jenkins運行時集成測試失敗
4.本地測試環境是WIN10 64bit; Jenkins在Ubuntu 16.04 64位服務器上的docker容器中運行,MySQL 5.7容器連接到同一個橋接網絡。
感謝@ rohit-thomas 。 我們將問題縮小到與URL主機相關的問題。
簡單的答案是將spring boot application.properties
中的JDBC URL主機更改為docker主機IP地址。 從
spring.datasource.url=jdbc:mysql://mysql:3306/database?
至
spring.datasource.url=jdbc:mysql://172.17.0.1:3306/database?
從Docker容器內部,如何連接到本機的本地主機?
這篇文章也有助於作為最終解決方案。
ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
...
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
...
我的結論是:
從映像構建的Jenkins容器可以使用其容器名稱或docker bridge網絡上的私有地址與MySQL容器進行通信。 但是,由於Jenkins構建的應用程序無法做到這一點。 由於MySQL容器端口已綁定到主機,因此應用程序可以通過主機端口與MySQL容器通信。
如果結論錯誤,歡迎提出意見。
您可以檢查的一些內容可能有助於您解決此問題。
在application.properties中嘗試使用docker主機IP地址。
從
spring.datasource.url = jdbc:mysql://mysql:3306/DATABASE_URI_PATH
至
spring.datasource.url = jdbc:mysql://192.168.99.100:33060/DATABASE_URI_PATH
注意:在docker run或docker文件中的端口時,您需要映射IP和端口。並在容器中使用相同的docker網絡。
驗證服務器應用程序是否可以訪問您的mysql,反之亦然。 進入docker容器並嘗試ping。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.