每日的數據同步任務中,會將在線業務庫的數據同步至 Hive,在剛上線的一段時間內,對 Hive 的 SQL 操作每隔十來天會出現 socket read timeout 的異常。該問題導致我經常凌晨收到告警然後起牀修復該問題,因爲該問題是偶現,不便復現,經過查閱 Hive JDBC 的源碼,定位問題爲 Hive JDBC 使用了 java.sql.DriverManager 中的靜態變量 loginTimeout 的值,而我們的工程中接入了八九種類型的 JDBC 驅動,部分類型還使用了連接池,先看看 java.sql.DriverManager 中的部分源碼:
依賴版本
版本:
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>2.3.2</version>
</dependency>
源碼分析
- 獲取到connection代碼:
HiveDriver client = new HiveDriver();
connection = client.connect(URL + HUE_PARAM, prop);
- client.connect源碼:
初始化hive connection時,將loginTimeout時間賦予了HiveConnection
對象的loginTimeout
。
- loginTimeout時間最終會賦予給socket對象的socketTimeOut時間。
解決方案
不升級版本方案:
HiveDriver client = new HiveDriver();
DriverManager.setLoginTimeout(500);
connection = client.connect(URL + HUE_PARAM, prop);
升級版本方案:
官方已經於 2021 年 2 月 17 日被修復併合並至 master 分支,詳情可查看該 PR: HIVE-12371 Adding a timeout connection parameter for JDBC #1611。
可以升級到及其後續版本:
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>3.1.3</version>
</dependency>