2012-10-29 17 views
8

Przeglądam SO przez jakiś czas i żuję mój kapelusz w procesie, ale nie mogę znaleźć dokładnego dopasowania do mojego problemu.
W skrócie otrzymuję doskonałe śledzenie stosu (org.apache.tomcat.jdbc.pool.ConnectionPool abandon) po 60 sekundach bezczynności, co jest normalnym zachowaniem dla kilku wątków po stronie serwera.
używam połączenia Tomcat JDBC (org.apache.tomcat.jdbc.pool.DataSource) bezpośrednio
Stos śledzenia:WebApp (Tomcat-jdbc) Połączone połączenie zrzucania DB porzuć wyjątek

 
    Oct 29, 2012 8:55:50 PM org.apache.tomcat.jdbc.pool.ConnectionPool abandon 
    WARNING: Connection has been abandoned PooledConnection[[email protected]]:java.lang.Exception 
     at org.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java:967) 
     at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:721) 
     at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:579) 
     at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:174) 
     at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:111) 
     at com.getsom.getConnection(DAO.java:1444) 
     at com.getsom.PreparedConnection.(PreparedConnection.java:48) 
     at com.getsom.Alarms.run(Alarms.java:492) 

Moi PoolProperties są skonfigurowane następująco:

PoolProperties pp = new PoolProperties(); 

    pp.setUrl(someValidUrl); 
    pp.setDriverClassName("com.mysql.jdbc.Driver"); 
    pp.setUsername(someUser); 
    pp.setPassword(somePassword); 
    pp.setJmxEnabled(true); 
    pp.setTestWhileIdle(true); 
    pp.setTestOnBorrow(true); 
    pp.setValidationQuery("SELECT 1"); 
    pp.setTestOnReturn(false); 
    pp.setValidationInterval(30000); 
    pp.setTimeBetweenEvictionRunsMillis(30000); 
    pp.setMaxActive(100); 
    pp.setInitialSize(10); 
    pp.setMaxWait(10000); 
    pp.setMinEvictableIdleTimeMillis(30000); 
    pp.setMinIdle(10); 

    pp.setLogAbandoned(true); 
    pp.setRemoveAbandoned(true); 
    pp.setRemoveAbandonedTimeout(60); 
    pp.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+ 
     "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");  

    setPoolProperties(pp); 

I miałem nadzieję, że setValidationInterval (30000) mnie uratuje, ponieważ 30 to niewiele w cyklu życia połączenia. W każdym razie pytanie brzmi:
Czego mi brakuje, aby utrzymać to połączenie na zawsze? Warto wiedzieć: Dlaczego przekroczono limit czasu funkcji, która odebrała połączenie, mimo że została wywołana 30 sekund wcześniej.

Odpowiedz

30

Mimo że spóźniłem się o ponad 1 rok na tę stronę, natknąłem się na to, ponieważ miałem podobne problemy i potrzebowałem rozwiązania. Więc pomyślałem, że podzielę się tym, co ostatecznie dla mnie zadziałało.

W moim przypadku, po znalezieniu i przeczytaniu tego artykułu >>>configuring-jdbc-pool-high-concurrency - Właśnie dodałem przechwytujący w ten sposób do mojej konfiguracji basenu;

"org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer" 

tak, że linia (z kodem zamieszczone powyżej) gdzie można zrobić setJdbcInterceptors(...) powinna teraz wyglądać następująco;

p.setJdbcInterceptors(
      "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;" 
      + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;" 
      + "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"); 

Wyjaśnienie - Cytując z artykułu, to mówi;

Chcemy mieć pewność, że po wykryciu, że połączenie jest nadal używane, zresetujemy licznik czasu oczekiwania, aby połączenie nie zostało uznane za porzucone. Robimy to poprzez wstawienie przechwytywacza.

Za każdym razem, gdy instrukcja jest przygotowywana lub wykonywane jest zapytanie, licznik zresetuje licznik porzucania w puli połączeń. W ten sposób ... wykonywanie wielu zapytań i aktualizacji nie spowoduje przekroczenia limitu czasu.

Pamiętając najprawdopodobniej przezwyciężyć ten problem już dawno temu, wciąż mam nadzieję, że to pomoże ktoś inny mający podobne problemy, które wpada na tej stronie, podobnie jak ja.

Pozdrawiam!

+8

Jeden rok na odpowiedź, dwa lata na akceptację :) – MonoThreaded

+0

Ta odpowiedź jest również moim rozwiązaniem! Dzięki chłopaki! – Samarland

2

Czy widziałeś informacje na stronie Tomcat dotyczące PoolConnection. Być może to, co potrzebne jest, aby spojrzeć na nieruchomości minEvictableIdleTimeMillis

Aby odpowiedzieć na to pytanie jesteś taktowaniu, bo jesteś sprawdzanie gotowości & porzucić połączenia co 30 sekund (patrz TimeBetweenEvictionRunsMillis) i ponieważ jesteś ustawienie evictable bezczynności na 30 sekund (patrz minEvictableIdleTimeMillis), a następnie skończysz z tym, co masz. Powiedziałeś, że otrzymujesz ten wyjątek w stanie bezczynności. Podejrzewam, że wyjątek jest wynikiem zamknięcia bezczynnego połączenia, a nie porzucenia połączenia. Z mojego rozumienia rezygnacji z połączenia używa się do przekroczenia czasu oczekiwania (w przeciwieństwie do bezczynnych połączeń).

Osobiście nie chciałbym mieć połączeń na zawsze, ponieważ niepotrzebnie zużywają zasoby (czyli połączenie z bazą danych). Bawiłbym się z moimi maksymalnymi połączeniami, biegami eksmisji i czasami bezczynności, aby zoptymalizować dla własnych potrzeb. Myślę, że możesz ustawić te wartości wystarczająco duże, by prawie na zawsze! To naprawdę zależy od tego, co robisz ...

Przykro mi, ale nie mogłem pomóc tutaj.

+0

Tak, czytałem to szeroko. Uważam, że ma to związek z porzuceniem czegoś więcej niż eksmisją. Zakładałem, że ConnectionPool utrzyma te połączenia przy życiu. – MonoThreaded

+0

Czy pojawia się błąd podczas wykonywania zapytania? Wydaje się dziwne, że zapytanie trwa dłużej niż 60 sekund! – ramsinb

+0

Nie. Wątek, o którym mowa, jest bezczynny. Jaki jest problem, ponieważ ConnectionPool zakłada, że ​​połączenie zostało porzucone. – MonoThreaded

1

ścieżka "removeAbandonedTimeout" w pliku konfiguracyjnym. powinno to być maks. uruchomione zapytanie w aplikacji. othewise będzie zamknąć połączenie w środku wykonanie

+0

Mam ten sam problem i już mam zestaw removeAbandonedTimeout, a to niestety nie pomaga. –

+0

Czy możesz wyjaśnić, jak "śledzić" ten atrybut zasobów w Tomcat? – Navigatron

1

Juste dodać tomcat7 w pliku conf/server.xml

jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState; 
org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer; 
org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer" 
1

Jeśli zdefiniować źródło danych w context.xml Tomcat następnie należy dodać ResetAbandonedTimer jak poniżej:

jdbcInterceptors="ConnectionState;StatementFinalizer;ResetAbandonedTimer" 

Po ustawieniu ResetAbandonedTimer, problem został rozwiązany w mojej aplikacji, z prośbą, aby dać mi znać czy jest jakiś związek między ResetAbandonedTimer kolektora i removeAbandoned = „true” removeAbandonedTimeout = „60”

0

Odpowiedzi na to pytanie były dla mnie bardzo pomocne.

Chociaż w moim przypadku miałem już skonfigurowany przechwytujący JDBC "ResetAbandonedTimer".

Jednak miałem zapytanie, które działało dłużej niż "removeAbandonedTimeout", który również skonfigurowałem. Po zwiększeniu "removeAbandonedTimeout" problem zniknął.

Powiązane problemy