Параметр checkoutTimeout в C3P0 мешает исключению при входе в систему - PullRequest
0 голосов
/ 06 июня 2019

Вот автономный скрипт Groovy, который воспроизводит ошибку.

@Grab(group='com.mchange', module='c3p0', version='0.9.5.4')
@Grab(group='com.microsoft.sqlserver', module='mssql-jdbc', version='6.4.0.jre7')

import com.mchange.v2.c3p0.*

ComboPooledDataSource datasource = new ComboPooledDataSource()

datasource.setJdbcUrl('jdbc:sqlserver://valid-db:1433;databaseName=dbName;socketTimeout=600000')
datasource.setDriverClass('com.microsoft.sqlserver.jdbc.SQLServerDriver')
datasource.setUser('myDb')
datasource.setPassword('wrong-pwd')
//datasource.setCheckoutTimeout(10000)

long time = System.currentTimeMillis()
try{
datasource.getConnection()
}finally{
println ((System.currentTimeMillis() - time) + " millis")
}

Вышеуказанный скрипт выводит следующее expected ошибка

31730 millis
<and...>
Login failed for user...

Когда я добавляю datasource.setCheckoutTimeout(10000) в скрипт, вот что он печатает.

20006 millis
<and...>
Caused by: com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool@57faccf9 -- timeout at awaitAvailable()

Нет никаких намеков на неудачный вход во всю трассировку стека. Может быть, я что-то упустил.

  • Почему в первом сценарии требуется 30 секунд, чтобы сообщить о неудачном входе в систему.
  • Почему он тратит 20 секунд, полностью глотает ошибку при входе в систему и сообщает об ошибке неправильного времени ожидания во втором сценарии.

Я мог бы пропустить некоторые важные настройки, чтобы избежать такого поведения.

1 Ответ

1 голос
/ 07 июня 2019

В первом случае требуется 30 секунд, чтобы сообщить о сбое, поскольку вы не установили ограничение, поэтому клиенты будут ждать в течение неопределенного времени, пока соединение не станет доступным. По умолчанию c3p0 делает 30 попыток получить соединение из базовой базы данных с задержкой в ​​одну секунду между каждой попыткой, прежде чем объявить об ошибке получения соединения и сообщить об этом ожидающим клиентам. Если вы хотите изменить это поведение, вы можете установить настройки c3p0 acquireRetryAttempts и acquireRetryDelay на все, что вы предпочитаете.

Во втором случае вы запрашиваете у c3p0 тайм-аут клиентов через 10 секунд, и это так. Что касается c3p0, получение соединения не завершилось неудачно. «Ошибка входа пользователя» не является причиной сбоя. Заданное вами время ожидания является причиной сбоя, поэтому c3p0 сообщает об этом.

Когда получение подключения окончательно завершается неудачно, ничего не глотается, ошибка регистрируется правильно. Но поток вашего клиента не имеет ничего общего с получением подключения. Весь смысл пула соединений состоит в том, чтобы отделить получение соединения уровня СУБД от проверок клиента. c3p0 «вспомогательные» потоки взаимодействуют с СУБД, а не с клиентским потоком.

Чтобы получить поведение, которое звучит так, как вам нужно, оставьте checkoutTimeout неустановленным, но установите для acquireRetryAttempts значение меньше 10. Затем, если данные для входа неверны, клиенты увидят ошибку при получении Соединения в течение 10 секунд.

...