Open
Description
Database Type
postgresql
Database Version
any
Druid Version
1.2.23
JDK Version
OpenJDK 17
Error SQL
case1. 用户通过druid properties配置socketTimeout和connectTimout参数
- 低版本的druid不会做时间转换,会直接透传给驱动,那么驱动会使用properties设置超时时间,此时单位是秒
- 高版本的druid对时间做了毫秒到秒的转换,要求用户做不兼容改动,将properties中配置时间
x1000
,配置为毫秒,使用者有可能并不知情,导致期望超时行为发生变化,此为不兼容改动
case2. 用户通过jdbc url设置socketTimeout和connectTimeout参数
实际创建连接时,pg驱动中会从url中提取socketTimeout和connectTimeout参数,则druid提供的properties会被驱动覆盖,而驱动期望的单位是秒。但是DruidAbstarctDataSource
中期望的timeout参数是以毫秒为单位,pg下会将毫秒转换为秒,此情况要求使用者url中配置的是毫秒单位。此外,setNetworkTimeout也是druid解析后的结果,对使用者要求是毫秒为单位。这就会导致socketTimeout需要按照你们期望的以毫秒为单位在url中配置。但是!!!connectTimeout是在驱动里面实现的,默认会乘1000,且druid后续不会像setNetowkTimeout一样有覆盖行为,这就导致用户配置url就必须以秒为单位配置。
结论:通过url配置的方式要求connectTimeout以秒为单位,socketTimeout以毫秒为单位配置,两个配置单位不一致
pg驱动里面实现的是秒,驱动会再乘1000的
private PGStream tryConnect(Properties info, SocketFactory socketFactory, HostSpec hostSpec, SslMode sslMode, GSSEncMode gssEncMode) throws SQLException, IOException {
int connectTimeout = PGProperty.CONNECT_TIMEOUT.getInt(info) * 1000;
String user = PGProperty.USER.getOrDefault(info);
String database = PGProperty.PG_DBNAME.getOrDefault(info);
SslNegotiation sslNegotiation = SslNegotiation.of((String)Nullness.castNonNull(PGProperty.SSL_NEGOTIATION.getOrDefault(info)));
if (user == null)
throw new PSQLException(GT.tr("User cannot be null", new Object[0]), PSQLState.INVALID_NAME);
if (database == null)
throw new PSQLException(GT.tr("Database cannot be null", new Object[0]), PSQLState.INVALID_NAME);
int maxSendBufferSize = PGProperty.MAX_SEND_BUFFER_SIZE.getInt(info);
PGStream newStream = new PGStream(socketFactory, hostSpec, connectTimeout, maxSendBufferSize);
try {
int socketTimeout = PGProperty.SOCKET_TIMEOUT.getInt(info);
if (socketTimeout > 0)
newStream.setNetworkTimeout(socketTimeout * 1000);
String maxResultBuffer = PGProperty.MAX_RESULT_BUFFER.getOrDefault(info);
newStream.setMaxResultBuffer(maxResultBuffer);
boolean requireTCPKeepAlive = PGProperty.TCP_KEEP_ALIVE.getBoolean(info);
newStream.getSocket().setKeepAlive(requireTCPKeepAlive);
boolean requireTCPNoDelay = PGProperty.TCP_NO_DELAY.getBoolean(info);
newStream.getSocket().setTcpNoDelay(requireTCPNoDelay);
int receiveBufferSize = PGProperty.RECEIVE_BUFFER_SIZE.getInt(info);
if (receiveBufferSize > -1)
if (receiveBufferSize > 0) {
newStream.getSocket().setReceiveBufferSize(receiveBufferSize);
} else {
LOGGER.log(Level.WARNING, "Ignore invalid value for receiveBufferSize: {0}",
Integer.valueOf(receiveBufferSize));
}
int sendBufferSize = PGProperty.SEND_BUFFER_SIZE.getInt(info);
if (sendBufferSize > -1)
if (sendBufferSize > 0) {
newStream.getSocket().setSendBufferSize(sendBufferSize);
} else {
LOGGER.log(Level.WARNING, "Ignore invalid value for sendBufferSize: {0}", Integer.valueOf(sendBufferSize));
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Receive Buffer Size is {0}",
Integer.valueOf(newStream.getSocket().getReceiveBufferSize()));
LOGGER.log(Level.FINE, "Send Buffer Size is {0}",
Integer.valueOf(newStream.getSocket().getSendBufferSize()));
}
if (sslNegotiation != SslNegotiation.DIRECT)
newStream = enableGSSEncrypted(newStream, gssEncMode, hostSpec.getHost(), info, connectTimeout);
if (!newStream.isGssEncrypted())
newStream = enableSSL(newStream, sslMode, info, connectTimeout);
if (socketTimeout > 0)
newStream.setNetworkTimeout(socketTimeout * 1000);
List<StartupParam> paramList = getParametersForStartup(user, database, info);
sendStartupPacket(newStream, paramList);
doAuthentication(newStream, hostSpec.getHost(), user, info);
return newStream;
} catch (Exception e) {
closeStream(newStream);
throw e;
}
}
Testcase Code
No response
Stacktrace Info
No response
Error Info
No response
Metadata
Metadata
Assignees
Labels
No labels