Проблемы с тайм-аутом подключения после периода бездействия

У нас есть API, который использует спящий режим в качестве инструмента ORM, и мы используем c3p0 в качестве обработчика пула соединений. У нас нет проблем, когда мы находимся под нагрузкой. Однако мы сталкиваемся с исключениями «невозможно получить соединение», когда API неактивен в течение дня или около того. Таким образом, если никто не использует API в выходные, мы получим ошибки подключения в понедельник утром.

Причина: java.sql.SQLException: время ожидания попытки клиента проверить соединение истекло.

Мы используем mysql в качестве базы данных. В своем исследовании я узнал, что mySQL делает соединения устаревшими через 8 часов или около того. Возможно, пул соединений выдает устаревшее соединение с клиентом и, следовательно, исключения времени ожидания соединения для клиента.

В настоящее время у нас нет настроенного тестирования соединения в C3Po. Скажем, если я использую IdleTestPeriod для проверки соединения до того, как они будут переданы клиенту пулом. Что произойдет, если все мои соединения в какой-то момент не пройдут проверку? Будут ли эти неудачные подключения удалены из пула, а новые активные подключения будут созданы снова?

В настоящее время это настройки c3p0, которые мы используем. Возможны ли другие причины этой проблемы?

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${----}"/>
        <property name="jdbcUrl" value="${----}"/>
        <property name="user" value="${----}"/>
        <property name="password" value="${------}"/>
        <property name="minPoolSize" value="5"/>
        <property name="acquireIncrement" value="5" />
        <property name="maxPoolSize" value="125" />
        <property name="maxStatements" value="10" />
        <property name="maxIdleTime" value="180" />
        <property name="maxIdleTimeExcessConnections" value="30" />
        <property name="checkoutTimeout" value="3000" />
        <property name="preferredTestQuery" value="SELECT 1" />
    </bean>

person Npa    schedule 31.07.2012    source источник


Ответы (2)


Итак, у вас есть checkoutTimeout 3 секунды (3000 мс). Это исключение, которое вы видите. Клиентам разрешается ждать только три секунды, чтобы проверить соединение из пула; если трех секунд недостаточно, они увидят ваше исключение.

Вопрос в том, почему клиенты так долго не могут получить соединение? Обычно проверка соединения — довольно быстрая операция. Но если все соединения извлечены, то клиентам придется ждать (медленного) получения соединения из базы данных.

Ваш пул настроен на довольно агрессивную отбраковку подключений. Любое количество подключений выше minPoolSize=5 будет уничтожено, если они простаивают более maxIdleTimeExcessConnections=30 секунд. Тем не менее, ваш пул настроен на крупномасштабные всплески: maxPoolSize=125. Предположим, что ваше приложение какое-то время молчит, а затем получает поток запросов на подключение от клиентов. В пуле быстро закончатся соединения, и он начнет получать, в пакетах сAcquireIncrement=5. Но если внезапно появилось 25 клиентов, а в пуле всего 5 подключений, не исключено, что 25-й клиент может истечь по тайм-ауту до получения подключения.

Вы можете многое сделать. Эти настройки являются раздельными, вы можете смешивать или сочетать их по своему усмотрению.

  1. Менее агрессивно отбрасывайте простаивающие «лишние» соединения, чтобы в целом у вашего пула была некоторая способность обслуживать всплески запросов. Вы можете полностью отказаться от maxIdleTimeExcessConnections и позволить Connections медленно увядать после maxIdleTime=180 секунд неиспользования. (Недостаток? Большее потребление ресурсов в течение более длительного времени в периоды бездействия.)

  2. Установите для minPoolSize более высокое значение, чтобы маловероятно, что пул увидит всплеск активности, для которого у него слишком мало подключений. (Недостаток? Больше постоянных ресурсов.)

  3. Удалите checkoutTimeout из вашей конфигурации. По умолчанию c3p0 позволяет клиентам бесконечно ждать соединения. (Недостаток? Возможно, вы предпочитаете, чтобы клиенты быстро сообщали об ошибке, а не ждали возможного успеха.)

Я не думаю, что проблема, которую вы наблюдаете, имеет непосредственное отношение к тестированию соединения или тайм-аутам MySQL как таковым, но это не значит, что вы не должны решать эти проблемы. Я прислушаюсь к совету nobeh по вопросу повторного подключения MySQL. (Я не большой пользователь MySQL.) Вам следует подумать о реализации тестирования подключения. У вас есть предпочтительный TestQuery, поэтому тесты должны быть достаточно быстрыми. Обычно я использую testConnectionOnCheckin и idleConnectionTestPeriod. См. http://www.mchange.com/projects/c3p0/#configuring_connection_testing.

Удачи!

person Steve Waldman    schedule 31.07.2012

В разделе Высокая доступность и кластеризация в MySQL Java Connector, взгляните на свойства; в частности autoReconnect и autoReconnetForPools. Используйте свойства в URL-адресе подключения JDBC. Раньше они помогали мне при использовании MySQL, Hibernate и C3P0. Надеюсь, что это поможет.

person nobeh    schedule 31.07.2012
comment
Примечание. Использование параметра autoReconnect не рекомендуется, поскольку не существует безопасного метода повторного подключения к серверу MySQL без риска некоторого повреждения состояния соединения или информации о состоянии базы данных. Вместо этого вы должны использовать пул соединений, который позволит вашему приложению подключаться к серверу MySQL, используя доступное соединение из пула. Средство автоматического повторного подключения устарело и может быть удалено в будущем выпуске. - person wiggin200; 16.06.2020