Восстановление источника данных Jboss после перезапуска базы данных - PullRequest
4 голосов
/ 23 января 2010

Закрытые соединения все еще в пуле соединений - почему?

servlet-

public class Index extends HttpServlet {

    TimeZoneService timeZoneService;

    public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException {
        WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
        timeZoneService = (TimeZoneService) ctx.getBean("timeZoneService");
        timeZoneService.loadAllTimeZones();
        System.out.println("Done");
    }
}

public interface TimeZoneService {
    void loadAllTimeZones();
}

public class TimeZoneServiceImpl implements TimeZoneService {

    private TimeZoneDao tzDao;
    private Map<Long, String> tzOid2JavaName = new HashMap<Long, String>();

    public void loadAllTimeZones() {
        List<TimeZone> timeZones = tzDao.findAllTimeZones();
        for (TimeZone tz : timeZones) {
            tzOid2JavaName.put(tz.getOid(), tz.getJavaName());
        }
    }

    public void setTzDao(TimeZoneDao tzDao) {
        this.tzDao = tzDao;
    }
}

public interface TimeZoneDao {
    List<TimeZone> findAllTimeZones() throws DataAccessException;  
}

public class TimeZoneDaoImpl extends JdbcDaoSupport implements TimeZoneDao {

    public List<TimeZone> findAllTimeZones() throws DataAccessException
    {
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT TZ.OID, TZ.JAVA_NAME FROM TIME_ZONE TZ");
        List<TimeZone> timeZones = getJdbcTemplate().query(sql.toString(), new RowMapper() {
            public Object mapRow(ResultSet rs, int i) throws SQLException {
                TimeZone tz = new TimeZone();
                tz.setOid(rs.getLong("OID"));
                tz.setJavaName(rs.getString("JAVA_NAME"));
                return tz;
            }
        });

        return timeZones;
    }
}

public class TimeZone {
    private Long oid;
    private String javaName;

    public Long getOid() {
        return this.oid;
    }

    public void setOid(Long oid) {
        this.oid = oid;
    }

    public String getJavaName() {
        return this.javaName;
    }

    public void setJavaName(String javaName) {
        this.javaName = javaName;
    }
}

весна-config.xml

<beans>

    <jee:jndi-lookup id="dataSource" jndi-name="java:/OracleDS"/>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="timeZoneDao" class="dao.impl.TimeZoneDaoImpl">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="timeZoneService" class="logic.impl.TimeZoneServiceImpl">
        <property name="tzDao" ref="timeZoneDao"/>
    </bean>

</beans>

web.xml

<web-app>

    <display-name>Spring</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            WEB-INF/spring-config.xml,classpath*:/META-INF/spring-config.xml</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>index</servlet-name>
        <display-name>Index page</display-name>
        <description>Landing page</description>
        <servlet-class>servlet.Index</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>index</servlet-name>
        <url-pattern>/index</url-pattern>
    </servlet-mapping>

    <!-- Session Timeout (in minutes) -->
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>
</web-app>

MySQL-ds.xml

<datasources> 
   <local-tx-datasource> 
      <jndi-name>OracleDS</jndi-name> 
      <connection-url>jdbc:mysql://localhost:3306/spring</connection-url> 
      <driver-class>com.mysql.jdbc.Driver</driver-class> 
      <user-name>spring_test</user-name> 
      <password>spring_test13</password> 
      <min-pool-size>1</min-pool-size> 
      <max-pool-size>5</max-pool-size> 
      <idle-timeout-minutes>2</idle-timeout-minutes> 
   </local-tx-datasource> 
</datasources>

Ответы [ 3 ]

7 голосов
/ 27 января 2010

Хорошо. Надеюсь, что кому-то пригодится следующее: -)

Существует настройка конфигурации источника данных - exception-sorter-class-name

Согласно Jboss это используется для a class that looks at vendor specific messages to determine whether sql errors are fatal and thus the connection should be destroyed. If none specified, no errors will be treated as fatal.

Если с использованием базы данных Oracle , эта конфигурация установлена ​​на org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter. В этом классе есть все коды ошибок, которые должны рассматриваться как фатальные, и, следовательно, соединение должно быть разрушено.

В Jboss 4 коды ошибок 17002 (сброс соединения) && 17008 (соединение закрыто) не включены. Они добавлены в Jboss 5. Поэтому, если вы используете Jboss 4 и задаетесь вопросом, почему соединения не восстанавливаются, попробуйте добавить отсутствующие коды.

2 голосов
/ 22 января 2013

Вот конфигурация проверки соединения с oracle DB для jboss 7.1 + :

<validation>
   <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.vendor.OracleValidConnectionChecker"/>
   <check-valid-connection-sql>select 1 from dual</check-valid-connection-sql>
   <stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.vendor.OracleStaleConnectionChecker"/>
   <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter"/>
</validation>

Теперь Jboss проверит каждое ваше соединение.

2 голосов
/ 24 января 2010

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

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

Однако на сайтах с низким трафиком, где ваша база данных может справиться с дополнительной нагрузкой, вы можете настроить свой источник данных так, чтобы JBoss проверял соединение перед передачей его в ваше приложение. Если соединение разорвано, JBoss удалит его из пула и получит новое, чтобы он выдержал перезапуск базы данных.

Любой, добавьте это в ваш mysql-ds.xml файл:

<check-valid-connection-sql>select 1 from mytable</check-valid-connection-sql>

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

См. Вики-документацию JBoss , чтобы узнать, как изменить эти файлы источника данных.

...