1. 从一个常见的 HIVE JDBC SocketTimeoutException 问题聊起

  • 在并发较高负载较大的大数据集群中,执行 HIVE SQL 常见的一个问题是 SocketTimeoutException 超时,即 “org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: Read timed out”,其完整报错信息如下;

  • 针对 HIVE JDBC 这类 SocketTimeoutException 超时问题,除了想办法提高集群性能或降低集群负载(比如错峰执行),我们也可以在HIVE JDBC 客户端,在应用级别配置使用更大的 hive thrift socket time out,从而减小 SocketTimeoutException 发生的概率;

  • 由于 hive 的 SocketTimeout,其底层直接获取的是 HiveConnection 的 LoginTimeout,而 HiveConnection 的 LoginTimeout,目前所有版本的HIVE,都需要通过静态方法 java.sql.DriverManager.setLoginTimeout(int seconds) 进行配置,所以无论应用是使用线程池如 Hikari/Druid/DBCP 创建和管理 HIVE JDBC 连接,还是直接创建和管理 HIVE JDBC 连接,在本质上,都需要显示或隐式地通过 java.sql.DriverManager.setLoginTimeout(int seconds)配置 LoginTimeout 进而配置 SocketTimeout;

  • 如果应用程序直接创建和管理 HIVE JDBC 连接:用户需要在 JVM 运行时会加载的某个类的成员方法或静态方法或静态代码段中,调用静态方法java.sql.DriverManager.setLoginTimeout(int seconds)配置静态变量 loginTimeout,即可间接配置 hive thrift socketTimeout;

  • 如果应用程序使用线程池如 Hikari 来创建管理 HIVE JDBC 连接: 除了上述方法,用户还可以显示配置 connectionTimeout 为非0值,此时 hikari 会基于用户配置的 connectionTimeout,自动推导然后调用静态方法 java.sql.DriverManager.setLoginTimeout(int seconds) 配置静态变量 loginTimeout,进而间接配置 hive thrift socketTimeout,推荐使用该方法进行配置;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# hive sql 作业 SocketTimeoutException 异常示例
[main] WARN com.zaxxer.hikari.pool.ProxyConnection - HikariPool-1 - Connection org.apache.hive.jdbc.HiveConnection@55a561cf marked as broken because of SQLSTATE(08S01), ErrorCode(0)
java.sql.SQLException: org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: Read timed out
at org.apache.hive.jdbc.HiveStatement.waitForOperationToComplete(HiveStatement.java:363)
at org.apache.hive.jdbc.HiveStatement.execute(HiveStatement.java:251)
at org.apache.hive.jdbc.HiveStatement.executeQuery(HiveStatement.java:434)
at com.zaxxer.hikari.pool.ProxyStatement.executeQuery(ProxyStatement.java:110)
at com.zaxxer.hikari.pool.HikariProxyStatement.executeQuery(HikariProxyStatement.java)
...
Caused by: org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: Read timed out
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:129)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:86)
at org.apache.thrift.transport.TSaslTransport.readLength(TSaslTransport.java:376)
at org.apache.thrift.transport.TSaslTransport.readFrame(TSaslTransport.java:453)
at org.apache.thrift.transport.TSaslTransport.read(TSaslTransport.java:435)
at org.apache.thrift.transport.TSaslClientTransport.read(TSaslClientTransport.java:37)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:86)
at org.apache.thrift.protocol.TBinaryProtocol.readAll(TBinaryProtocol.java:429)
at org.apache.thrift.protocol.TBinaryProtocol.readI32(TBinaryProtocol.java:318)
at org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:219)
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:77)
at org.apache.hive.service.rpc.thrift.TCLIService$Client.recv_GetOperationStatus(TCLIService.java:467)
at org.apache.hive.service.rpc.thrift.TCLIService$Client.GetOperationStatus(TCLIService.java:454)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.hive.jdbc.HiveConnection$SynchronizedHandler.invoke(HiveConnection.java:1412)
at com.sun.proxy.$Proxy2.GetOperationStatus(Unknown Source)
at org.apache.hive.jdbc.HiveStatement.waitForOperationToComplete(HiveStatement.java:332)
... 5 more
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:127)

2. JDBC 超时相关参数以及超时相关接口和方法总结

总体而言,JDBC 的超时有以下几种:

  • 事务超时transaction timeout:事务超时可以用来限制某个事务中所有 statement 语句的处理时间之和的最大值,简单来说,事务超时 transaction timeout = 语句超时 statement/query timeout * 事务中语句个数 + 其他耗时(如业务代码处理时间,gc 垃圾回收时间等),事务超时一般在应用框架中进行配置, 如 spring 中,可以使用注解 @Transactional 指定;

  • 查询超时 query timeout:有时也被称为语句超时 statement timeout,可以用来限制某个 statement 语句(可以是增删改查)的最大执行时间,若该 sql语句在该超时时间内还没有返回执行结果,应用端的数据库驱动程序就会抛出超时异常,并发送取消执行的信号给远程的数据库管理系统,由数据库管理系统取消该语句的执行;(所以底层依赖健康的TCP连接);

  • 连接超时 connectTimeout:有时也被称为网络超时 NetworkTimeout,是驱动程序建立 JDBC 底层的 TCP 连接的超时时间;

  • 登录超时 loginTimeout: 登录超时是数据库用户成功登录到数据库服务器的超时时间,由于用户登录数据库服务器时,底层包含了和数据库服务器之间的 tcp 连接的建立,也包含了数据库服务器对用户的认证,所以一般而言,需要配置登录超时 > 连接超时;

  • TCP 套接字超时( TCP socket timeout):由于应用程序通过 TCP 协议读写网络数据包,都是通过 TCP/IP 协议栈的 socket api 进行的,所以常规的套接字超时 socket timeout 同样适用于 JDBC 应用程序,此时应用程序通过 socket timeout 来检测和感知网络层面 TCP 连接的异常,从而避免僵死连接造成的无限等待;(TCP是面向连接的协议,但这里的连接是虚拟的,是动态的,也是不对等的,对这块感兴趣的朋友,可以关注笔者对 tcp/ip 协议栈,对 tcpdump/wireshark/packetdrill 工具的相关分享文章);

  • 关于这些超时的详细分析,见笔者以往编写的另一篇文章《深入源码和内核,一篇文章彻底理解数据库的各种超时参数-事务超时/查询超时/连接超时/登录超时/套接字超时》;

::: hljs-center

image.png

:::

3. HIVE JDBC 超时相关接口方法及其对各种超时参数的支持情况

  • Hive 作为大数据领域数据仓库的解决方案,提供了 SQL 供用户查询分析存储在分布式存储系统如 HDFS 中的海量数据,所以其在底层也必然实现了 JDBC 的相关接口方法;

  • HIVE3 通过 ACID 事务表进一步提供了对并发读写和记录级别增删改的支持,其对事务的支持进一步加强了,更像传统的 RDBMS 数据库了,但是 HIVE 毕竟不是传统的 RDBMS 数据库,其没有类似 binlog/redolog/undolog 的概念,在执行作业时仍会自动提交每个 statement 且不支持事务的 commit/rollback,同时其 SQL 查询性能一般也是秒或分钟级别而达不到数据库的毫秒级别,在并发支持上也达不到传统 RDBMS 的级别;

  • 通过查看 hive jdbc 源码中的相关接口与方法可知,其对超时相关参数的支持并不完善,远不如 RDBMS,甚至 HiveDataSource 和 HiveConnection 在对 loginTimeout 的配置上也不一致,HiveDataSource不支持配置loginTimeout,而HiveConnection支持配置 loginTimeout;

  • HiveDataSource 不支持配置 LoginTimeout, 参见源码可见,HiveDataSource#setLoginTimeout 直接抛出了异常 throw new SQLException(“Method not supported”);

  • HiveConnection 不支持配置 NetworkTimeout,参见源码可见,HiveConnection#setNetworkTimeout 直接抛出异常:throw new SQLException(“Method not supported”);

  • HiveConnection 可以配置 LoginTimeout,参见源码可知,HiveConnection#setupLoginTimeout,获取的就是 DriverManager.getLoginTimeout());(注意 DriverManager 中该方法为静态方法而不是成员方法)

  • HiveStatement的不同版本在支持配置 queryTimeout 的情况上并不相同同:参加源码可知,早期 1.3.0 之前的版本,HiveStatement#setQueryTimeout 会直接抛出异常 throw new SQLException(“Method not supported”),中期版本只可以配置 queryTimeout 为0即没有 timeout 机制,而2.1.0 之后的新版本则支持配置该 queryTimeout 参数,相关Jira 为 HIVE-10726 和 HIVE-4924;

image.png
image.png

  • HIVE JDBC 超时相关的接口类与方法,如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # JDBC API 相关接口类与方法
    - java.sql.DriverManager#setLoginTimeout
    - java.sql.Driver
    - javax.sql.CommonDataSource#setLoginTimeout
    - javax.sql.DataSource#setLoginTimeout
    - javax.sql.XADataSource#setLoginTimeout
    - javax.sql.ConnectionPoolDataSource#setLoginTimeout
    - java.sql.Connection#setNetworkTimeout
    - java.sql.Statement#setQueryTimeout
    - javax.sql.RowSet#setQueryTimeout
    # hive jdbc 相关接口类与方法
    - org.apache.hive.jdbc.HiveDriver
    - org.apache.hive.jdbc.HiveDataSource#setLoginTimeout: 直接抛出异常 throw new SQLException("Method not supported");
    - org.apache.hive.jdbc.HiveConnection#setNetworkTimeout: 直接抛出异常:throw new SQLException("Method not supported");
    - org.apache.hive.jdbc.HiveConnection#setupLoginTimeout:查看源码可知,获取的就是 DriverManager.getLoginTimeout());
    - org.apache.hive.jdbc.HiveStatement#setQueryTimeout:不同版本实现不同,早期1.3.0之前的版本, 直接抛出异常 throw new SQLException("Method not supported"),中期版本只可以配置 queryTimeout 为0,2.1.0之后的新版本则支持配置该 queryTimeout 参数;

4. 从源码角度细致分析 HiveStatement 中的 thrift socket timeout 是如何赋值的

  • 仔细查看并跟踪源码可以获悉,HiveStatement 中的 thrift socket timeout,其底层直接获取的是 HiveConnection 的 LoginTimeout;

  • 也就是说,hive 会基于 loginTimeout 自动推导并配置 socketTimeout;

  • 而 HiveConnection 的 LoginTimeout,目前所有版本的HIVE,都是通过静态方法 java.sql.DriverManager.getLoginTimeout 获取的静态变量loginTimeout,其默认值为0;

image.png
image.png

  • 相关源码即调用链如下,大家可以自己分析下;
    1
    2
    org.apache.hive.jdbc.HiveConnection#createUnderlyingTransport =》org.apache.hive.service.auth.HiveAuthFactory#getSSLSocket(java.lang.String, int, int) =》org.apache.thrift.transport.TSSLTransportFactory#getClientSocket(java.lang.String, int, int) =》org.apache.thrift.transport.TSSLTransportFactory#createClient =》
    java.net.Socket#setSoTimeout
    image.png
    image.png
    image.png
    image.png
    image.png

5. 当应用程序直接创建和管理 HIVE JDBC 连接时,如何配置 HiveStatement 中的 thrift socket timeout

  • 如上文分析所述,hive thrift socket time out,其底层直接获取的是 HiveConnection 的 LoginTimeout,也就是说,hive 会基于 loginTimeout 自动推导并配置 socketTimeout;

  • 而 HiveConnection 的 LoginTimeout,目前所有版本的HIVE,都是通过静态方法 java.sql.DriverManager.getLoginTimeout 获取的静态变量loginTimeout,其默认值为0;

  • 所以应用程序无论是使用线程池如 Hikari/Druid/DBCP 创建管理 HIVE JDBC 连接,还是直接创建管理 HIVE JDBC 连接,在本质上,都需要通过静态方法java.sql.DriverManager.setLoginTimeout(int seconds)配置静态变量 loginTimeout,从而间接配置配置 socketTimeout;

  • 由于方法 java.sql.DriverManager.setLoginTimeout(int seconds) 和 java.sql.DriverManager.getLoginTimeout() 是静态方法而不是实例方法,所以同一 JVM 中,所有引用了静态类 DriverManager 中的静态变量 loginTimeout 的 JDBC 驱动,都可能会收到影响,具体某 JDBC 驱动是否受到影响,取决于其具体实现;

  • 通过查看常见数据库驱动的源码可知,mysql/pg/oracle 驱动的 JDBC 连接,都没有引用该静态类 DriverManager 中的静态变量 loginTimeout以配置其 loginTimeout/connectTimeout/socketTimeout 等超时参数:

    • mysql 可以通过 url 指定 connectTimeout/socketTimeout 超时参数,其单位是毫秒,如:jdbc:mysql://localhost:3306/ag_admin?useUnicode=true&characterEncoding=UTF8&connectTimeout=60000&socketTimeout=60000
    • pg 也可以通过url 指定 指定 connectTimeout/socketTimeout 超时参数,不过其单位是秒:jdbc:postgresql://localhost/test?user=fred&password=secret&&connectTimeout=60&socketTimeout=60
    • oracle 的 thin jdbc driver,不支持通过 URL 参数指定套接字的连接超时和读写超时,而是需要通过系统参数 oracle.net.CONNECT_TIMEOUT 和 oracle.jdbc.ReadTimeout 来分别指定,这两个参数的单位都是毫秒,默认值都是0,(读写超时参数,在 10.1.0.5 以下版本的驱动中是 oracle.net.READ_TIMEOUT,在 10.1.0.5 以上的版本中才是 oracle.jdbc.ReadTimeout),比如可以通过 OracleDatasource.setConnectionProperties(java.util.Properties prop) 指定,使用 DBCP 时可以通过 BasicDatasource.setConnectionProperties(java.util.Properties prop)或 BasicDatasource.addConnectionProperties(java.util.Properties prop)指定;
  • 所以,如果应用程序直接创建和管理 HIVE JDBC 连接,只需要在 JVM 运行时会加载的某个类的成员方法或静态方法或静态代码段中,调用静态方法java.sql.DriverManager.setLoginTimeout(int seconds)配置静态变量 loginTimeout,即可间接配置 hive thrift socketTimeout;

  • 事实上,有不少案例,并没有显示在创建 HIVE 连接的相关代码段中调用该静态方法,但由于 JVM 加载的其它类中有些地方隐式地调用了该静态方法,导致 hive thrift socketTimeout受到了影响;

6. 当应用程序通过数据库连接池创建和管理 HIVE JDBC 连接时,如何配置 HiveStatement 中的 thrift socket timeout

  • 如上文分析所述,hive thrift socket time out,其底层直接获取的是 HiveConnection 的 LoginTimeout,也就是说,hive 会基于 loginTimeout 自动推导并配置 socketTimeout;

  • 而 HiveConnection 的 LoginTimeout,目前所有版本的HIVE,都是通过静态方法 java.sql.DriverManager.getLoginTimeout 获取的静态变量loginTimeout,其默认值为0;

  • 所以应用程序无论是使用线程池如 Hikari/Druid/DBCP 创建管理 HIVE JDBC 连接,还是直接创建管理 HIVE JDBC 连接,在本质上,都需要通过静态方法java.sql.DriverManager.setLoginTimeout(int seconds)配置静态变量 loginTimeout,从而间接配置配置 socketTimeout;
    z

  • 查看数据库连接池 hikari 的源码可知,hikari 会基于用户配置的 connectionTimeout,自动推导然后调用上述方法配置 DriverManager 中的静态变量 LoginTimeout:当 connectionTimeout 配置为非0值时,LoginTimeout 的值即是 connectionTimeout 加上500毫秒,且其值最小为1;

  • Hikari 通过 DriverDataSource 创建 JDBC 连接时(该类是 hikari 创建 JDBC 连接的方法之一),配置 LoginTimeout 的方法,就是通过调用静态方法 java.sql.DriverManager.setLoginTimeout(int seconds) 和 java.sql.DriverManager.getLoginTimeout() 来设置和获取静态变量 LoginTimeout;

  • 所以,如果应用程序使用线程池如 Hikari 来创建管理 HIVE JDBC 连接时:

    • 用户可以在 JVM 运行时会加载的某个类的成员方法或静态方法或静态代码段中,调用静态方法java.sql.DriverManager.setLoginTimeout(int seconds) 配置静态变量 loginTimeout,进而间接配置 hive thrift socketTimeout;
    • 用户可以显示配置 connectionTimeout 为非0值,此时 hikari 会基于用户配置的 connectionTimeout 自动推导然后调用静态方法 java.sql.DriverManager.setLoginTimeout(int seconds) 配置静态变量 loginTimeout,进而间接配置 hive thrift socketTimeout;
    • 推荐使用后一种方法,即用户显示配置 connectionTimeout 为非0值,由 hikari 基于用户配置的 connectionTimeou自动推导并配置静态变量 loginTimeout,进而间接配置 hive thrift socketTimeout;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public static HikariDataSource getHikariDataSource() throws Exception {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(url);
hikariConfig.setUsername(user);
hikariConfig.setPassword(password);
hikariConfig.setDriverClassName(HIVE_DRIVER_CLASS_NAME);
// 配置最小连接数,建议默认为0
hikariConfig.setMinimumIdle(HIVE_DATASOURCE_MIN_IDLE_SIZE);
hikariConfig.setMaximumPoolSize(HIVE_DATASOURCE_MAX_POOL_SIZE);
//配置空闲超时时间,建议默认为1分钟甚至30秒
hikariConfig.setIdleTimeout(HIVE_DATASOURCE_IDLE_TIMEOUT);
logger.info("logintimeout in getHikariDataSource():"+ String.valueOf(DriverManager.getLoginTimeout()));
// hikari 根据 connectionTimeout 设置了全局的 DriverManager.setLoginTimeout(seconds);
// 参见: com.zaxxer.hikari.pool.PoolBase.setLoginTimeout 和 com.zaxxer.hikari.util.DriverDataSource.setLoginTimeout
//配置为0,即代表 Integer.MAX_VALUE, 参见:com.zaxxer.hikari.HikariConfig.setConnectionTimeout
hikariConfig.setConnectionTimeout(5 * 1000);
hikariConfig.setValidationTimeout(3 * 1000);
// hikariConfig.setConnectionTimeout(10 * 1000);
// hikariConfig.setValidationTimeout(10 * 1000);
logger.info("logintimeout in getHikariDataSource():"+ String.valueOf(DriverManager.getLoginTimeout()));
hikariConfig.setKeepaliveTime(5 * 60 * 1000);
hikariConfig.setMaxLifetime(1 * 60 * 60 * 1000);
hikariConfig.setLeakDetectionThreshold(10 * 60 * 1000);
hikariConfig.setConnectionInitSql("set hive.execution.engine=spark");
logger.info("logintimeout in getHikariDataSource():"+ String.valueOf(DriverManager.getLoginTimeout()));
//
HikariDataSource dataSource = new HikariDataSource(hikariConfig);
logger.info("logintimeout in getHikariDataSource():"+ String.valueOf(DriverManager.getLoginTimeout()));

return dataSource;
}

image.png
image.png
image.png
image.png

7. 相关源码与参考连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# JDBC API 相关类与方法
java.sql.DriverManager#setLoginTimeout
javax.sql.CommonDataSource#setLoginTimeout
java.sql.Connection#getNetworkTimeout
java.sql.Connection#setNetworkTimeout
java.sql.Statement#setQueryTimeout

# hikari 相关类与方法
com.zaxxer.hikari.HikariDataSource#setLoginTimeout
com.zaxxer.hikari.pool.PoolBase#setLoginTimeout
com.zaxxer.hikari.HikariConfig#setConnectionTimeout
com.zaxxer.hikari.pool.PoolBase#createNetworkTimeoutExecutor
com.zaxxer.hikari.pool.PoolBase#getLoginTimeout: 5
com.zaxxer.hikari.util.DriverDataSource#getLoginTimeout com.zaxxer.hikari.util.DriverDataSource#setLoginTimeout

# hive 相关类与方法
org.apache.hive.jdbc.HiveDriver
org.apache.hive.jdbc.HiveStatement#setQueryTimeout
org.apache.hive.jdbc.HiveConnection#setupLoginTimeout:copy loginTimeout from driver manager. Thrift timeout needs to be in millis
org.apache.hive.jdbc.HiveConnection#setNetworkTimeout: not supported;
org.apache.hive.jdbc.HiveDataSource#setLoginTimeout:not supported
org.apache.hadoop.hive.ql.exec.Utilities#setQueryTimeout
org.apache.hive.jdbc.HiveStatement#runAsyncOnServer
org.apache.hive.service.rpc.thrift.TExecuteStatementReq#setQueryTimeout
org.apache.hive.jdbc.HiveConnection#createBinaryTransport
org.apache.hive.jdbc.HiveConnection#createUnderlyingTransport
org.apache.hive.service.auth.HiveAuthFactory#getSSLSocket(java.lang.String, int, int)
org.apache.thrift.transport.TSSLTransportFactory#getClientSocket(java.lang.String, int, int)
org.apache.thrift.transport.TSSLTransportFactory#createClient
// 相关jira:
https://issues.apache.org/jira/browse/HIVE-22196
https://issues.apache.org/jira/browse/HIVE-6679
https://issues.apache.org/jira/browse/HIVE-12371


// hikari创建 hive jdbc 连接:
com.zaxxer.hikari.HikariDataSource#HikariDataSource(com.zaxxer.hikari.HikariConfig)
com.zaxxer.hikari.pool.HikariPool#HikariPool
com.zaxxer.hikari.pool.HikariPool#checkFailFast
com.zaxxer.hikari.pool.HikariPool#createPoolEntry
com.zaxxer.hikari.pool.PoolBase#newConnection
//根据 HikariConfig 传入 dsClassName/ds/jdbcUrl,走不同分支,配置 jdbcUrl则走分支:
com.zaxxer.hikari.util.DriverDataSource#getConnection(java.lang.String, java.lang.String),此后基于 org.apache.hive.jdbc.HiveDriver#connect 创建连接,底层调用 org.apache.hive.jdbc.HiveConnection#HiveConnection,此时配置了LoginTimeout(基于DriverManager.getLoginTimeout())
com.zaxxer.hikari.pool.PoolBase#setupConnection //通过方法getAndSetNetworkTimeout,根据validationTimeout配置 NetworkTimeout,底层调用 HiveConnection#getNetworkTimeout,会报错不支持该方法
com.zaxxer.hikari.pool.PoolBase#initializeDataSource //构造器自动调用,底层又调用#setLoginTimeout,基于connectionTimeout 推导并配置 LoginTimeout,最小配置为1,底层调用的是com.zaxxer.hikari.util.DriverDataSource#setLoginTimeout,其底层是 DriverManager.setLoginTimeout(seconds);

本文转载于 michaelli