Подтвердить что ты не робот

Spring приложение потеряет соединение с MySql через 8 часов. Как правильно настроить?

У меня есть приложение Spring, которое, я считаю, использует пул соединений DBCP для подключения к базе данных MySql. Я говорю, верю, потому что это не та область, в которой я очень силен, и я не уверен, если все настроено правильно. У меня нет проблем с запуском приложения, и все работает нормально. Проблема возникает в одночасье. Приложение не сильно используется, и в одночасье он, по-видимому, теряет связь с MySql. Я заглянул в нее и узнал, что у MySql есть 8-часовое окно, а затем оно отключается или что-то еще. Я в порядке с этим, но когда пользователь пытается войти в систему по утрам, у них появляется ошибка:

Сбой связи. Последний пакет успешно получил 60 000 000 000 000 000 в прошлом. Последний пакет успешно установлен на 15 мс назад.

Это проблема. Мне нужно, чтобы они могли снова подключаться утром, не сталкиваясь с этим вопросом. Единственный способ, с помощью которого я могу это исправить, - это подпрыгнуть на сервере Tomcat. От взгляда на это кажется, что пул DBCP должен быть в состоянии как-то предотвратить это, но я не могу найти надежный источник информации о том, как его настроить. Я надеюсь, что кто-то здесь может дать мне некоторое представление. Вот моя текущая конфигурация, сделанная в файле Spring xml:

приложение-data.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:annotation-config />
<context:component-scan base-package="com.vz.sts.domain" />
<context:component-scan base-package="com.vz.sts.persistence" />
<context:component-scan base-package="com.vz.sts.service" />

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="database" value="MYSQL" />
            <property name="showSql" value="true" />
        </bean>
    </property>
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/app" />
    <property name="username" value="root" />
    <property name="password" value="admin" />
    <property name="initialSize" value="5" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="jdbcUserService" class="org.springframework.security.provisioning.JdbcUserDetailsManager">
    <property name="dataSource" ref="dataSource"/>
    <property name="authenticationManager" ref="authenticationManager"/>
</bean>

<bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
    <property name="userPropertyToUse" value="username" />
</bean>

<tx:annotation-driven />
</beans>

Я не уверен, какие конкретные свойства мне нужно добавить, чтобы приложение могло повторно подключиться к базе данных. Я не возражаю, если он закрывает соединение по истечении нескольких часов, но он должен автоматически подключаться и не выдавать такие ошибки. Я даже не уверен, что он фактически настроен на использование пула соединений. Поэтому любая помощь будет очень признательна, спасибо.

UPDATE

Я нашел эту страницу, и я думаю, что все, что мне нужно сделать, это добавить свойство ValidationQuery. Может ли кто-нибудь проверить, повлияет ли это на желание, оставив все остальное по умолчанию? Я полагаю, что тогда будет использоваться testOnBorrow аспект DBCP. Я не совсем понимаю, что объяснение говорит testOnBorrow, но я думаю, что это будет делать то, что я хочу. Кто-нибудь подтверждает? Спасибо.

4b9b3361

Ответ 1

Короткий ответ - этого должно быть достаточно. DBCP поддерживает тестирование соединения при заимствовании из пула соединений (по умолчанию), но также поддерживает тестирование при возврате и тестировании в режиме ожидания.

Также стоит понять, что здесь может быть неправильным. Похоже, что что-то между вашим сервером Tomcat и базой данных удаляет бездействующее соединение после таймаута (например, маршрутизатор или брандмауэр). Проблема заключается в том, что Tomcat полагает, что он все еще имеет правильное соединение, пытается выполнить некоторую работу с соединением и терпит неудачу, но поддерживает соединение и возвращает его в пул. Теперь любая дальнейшая попытка поговорить с базой данных не удастся, если ей будет присвоено такое же поврежденное соединение из пула.

Я думаю, что Майкл Нигард отлично "Отпусти это!" книгу, которая описала этот сценарий в одной из его историй о траншеях.

Вы также захотите посмотреть, как MySQL очищает мертвые соединения, как если Tomcat теряет соединение через 8 часов, DB также не будет знать о неудавшемся соединении.

В последнем случае, если вы используете Tomcat 7, переключитесь на новый пул соединений поскольку он обеспечивает лучшую производительность, чем DBCP.

Ответ 2

Мой друг, DBCP делает обещание, которое он не может сохранить. Хехе. Я столкнулся с этой проблемой, и она дошла до какого-то нового брандмауэра, который недавно запустил средние прерывания простоя с простоями дольше X часов. Таким образом, Db не смог уведомить моего клиента (и его сокет) о том, что соединение идет вниз, а сокет остается открытым, поэтому пул не мог знать, что соединение не доступно. Результат: первая попытка запроса утром потерпела неудачу с таймаутом, а вторая работала так, как ожидалось. Даже с validationQuery, DBCP не проверял уже действующий conn (не спрашивайте меня, почему, я только что узнал об этом)

Решение 1? Из-за того, что это была производственная среда (да, много пота), быстрая лошадь должна была создать отдельный поток, который отправлял бы вопрос с уверенностью в БД, используя пул каждый... X/4 часа. Он сохранил новый брандмауэр /WAF от измельчения моего разъема!

Решение 2? Проверьте инфраструктуру. Проверьте целостность. Проверьте согласованность скорости и режима сетевых интерфейсов (например, полный дуплекс, 100 М). Проверьте настройки сервера Db (нет чистой энергии, сохраняющей энергию). И, возможно, работа с зондом в решении 1.

ИЗМЕНИТЬ. testOnBorrow и validationQuery должны работать при нормальных обстоятельствах. Отображение пула с логическими каналами и физическим сотовым btw-клиентом и сервером. testOnBorrow проверяет, действительно ли канал, прежде чем передать его вашему запросу. Для этого используется validationQuery.