【Azure 應用服務】App Service 無法連接到Azure MySQL服務,報錯:com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
- 2021 年 11 月 25 日
- 筆記
- 【Azure 應用服務】, App Service, Azure Developer, Communications link failure, JDBC連接MYSQL
問題描述
App Service使用jdbc連接MySQL服務,出現大量的 Communications link failure:
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
問題分析
最開始出現連接不上的原因,懷疑是MySQL服務的IP地址白名單沒有配置正確的App Service 出站IP。但是根據錯誤提示,發現明顯不對,因為如果是IP地址不允許訪問,它的錯誤消息應該是:
Client with IP address '183.2xx.xx.xx' is not allowed to connect to this MySQL server.
所以不應該是MySQL伺服器對IP白名單設置的問題。
為了深入找出問題,單獨用Java Spring Boot來寫一個簡單的資料庫連接程式碼,根據MySQL官方的程式碼://docs.azure.cn/zh-cn/mysql/connect-java
POM.XML內容為:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="//maven.apache.org/POM/4.0.0" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <properties> <java.version>1.8</java.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.20</version> </dependency> </dependencies> </project>
註:這裡使用的 mysql-connector-java 依賴版本為 8.0.20
Java Main函數程式碼:
public static void main(String[] args) { String url = "jdbc:mysql://xxxxxx.mysql.database.chinacloudapi.cn:3306/xxxxxx?useSSL=true&requireSSL=false&characterEncoding=utf8&serverTimezone=UTC"; String username = "xxxxxx@xxxxxx"; String password = "xxxxxxxxxxxx"; try { Connection connection = DriverManager.getConnection(url, username, password); System.out.println(connection.getMetaData().getURL()); connection.close(); System.out.println("connected!"); } catch (SQLException e) { // TODO Auto-generated catch block System.out.println(e.getMessage()); return; // return because nothing can be done w/out a connection } }
同樣的資料庫連接字元串,運行結果正常。根據驗證結果對比,出現 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, 的JDBC版本為 8.0.15, 所以瞬間定位問題原因:客戶端jdbc的驅動問題。
根據這一判斷,再次檢查了MySQL的版本為8.0並且為單實例(Single Server)。而微軟的官方文檔中提示了 use 8.0.17+ with MySQL 8.0 (//docs.microsoft.com/en-us/azure/mysql/concepts-compatibility#mysql-drivers)

隨後,對mysql-connector jdbc的版本 8.0.17, 8.0.18, 8.0.19 這三個版本進行驗證,看是否不會出現 Communications link failure 異常:
8.0.17 Error

8.0.18 Error

8.0.19 Successful

經過以上驗證,得出微軟官方文檔中的 8.0.17+有問題,需要在8.0.19+的驅動版本後才能成功。(一個調查了三天的大坑)
參考資料
將 Java 和 JDBC 與 Azure Database for MySQL 配合使用 : //docs.azure.cn/zh-cn/mysql/connect-java


