2013-08-05 5 views
10

Mam aplikację internetową (używając Spring 3.1), która używa @ Zaplanowanej Adnotacji do okresowego wykonywania zadania roboczego (zaplanowane opóźnienie). Zadanie robocze otwiera połączenie z AWS DynamoDb i wykonuje niektóre operacje odczytu/aktualizacji DB. Po zatrzymaniu aplikacji webowej (od menedżera Tomcat) otrzymuję tę wiadomość w formacie catalina.out:Spring MVC WebApp: @schedule: java-sdk-http-connection-reaper: Nie udało się zatrzymać

"POWAŻNIE: Wydaje się, że aplikacja internetowa [] uruchomiła wątek o nazwie [java-sdk-http-reaper] ale nie udało się tego zatrzymać, bardzo prawdopodobne jest, że spowoduje to wyciek pamięci ".

Mam wrażenie, że ma to coś wspólnego z moim zaplanowanym zadaniem, które wciąż działa, nawet po zatrzymaniu Tomcat.

@Service 
public class TaskScheduler implements ApplicationListener<ContextClosedEvent>{ 

@Autowired 
private WorkerTask workerTask; 

AmazonDynamoDBClient myDbConn = null; 

    private TaskScheduler() {  
    myDbConn = new AWSConnector("aws.properties").getDynamoConnection(); 
    } 

/* 
* Will be repeatedly called, 10 seconds after the finish of the previous 
* invocation. 
*/ 
@Scheduled(fixedDelay=100000) 
public void process() { 
    System.out.println("Scheduling worker task"); 
      //worker task does some db read/writes 
    Future<String> status = workerTask.work(myDbConn); 
    if (status.isDone()) { 
     System.out.println("Completed Task"); 
     return; 
    } 

} 

@Override 
public void onApplicationEvent(ContextClosedEvent arg0) { 
    if(event instanceof ContextClosedEvent) { 
     // TODO Auto-generated method stub 
     if(myDbConn != null) { 
     this.myDbConn.shutdown(); 
     } 
      } 

} 

dyspozytor-servlet.xml:

<task:annotation-driven scheduler="taskScheduler"/> 
<task:scheduler id="taskScheduler" pool-size="2"/> 
...... 
<bean id="TaskScheduler" class="com.sample.TaskScheduler"/> 

robię to prawidłowo? a) Nie uruchamiam jawnie TaskScheduler. Zakładam, że wiosna dba o uruchomienie tej usługi. Wywoływane jest "this.myDbConn.shutdown()". Mimo to dostaję błąd. Używam Spring MVC.

Odpowiedz

12

Jest to prawdopodobnie spowodowane przez bibliotekę AWS, który rozpoczyna wątek w tle zwanego com.amazonaws.http.IdleConnectionReaper

Można go zamknąć poprzez wdrożenie ServletContextListener zamknąć go na zamknięcie

public class YourListener implements ServletContextListener { 

@Override 
public void contextInitialized(ServletContextEvent contextEvent) { 

} 

@Override 
public void contextDestroyed(ServletContextEvent contextEvent) { 

    try { 
     com.amazonaws.http.IdleConnectionReaper.shutdown(); 
    } catch (Throwable t) { 
     // log the error 
    } 
} 
} 

i dodając to do web.xml

<listener> 
    <listener-class> 
     your.package.YourListener 
    </listener-class> 
</listener> 
+0

Podoba mi się ta odpowiedź, chociaż poniżej może działać. Odkąd używam AWS SDK z innego słoika, którego wewnętrznych elementów nie znam. –

7

miałem ten problem jak dobrze, ale zdecydowałem się na rozwiązanie alternatywne do tych @ David_Wartell powyżej.

I wytropił klasy, który został tworzenia obiektu naruszające/obiekty z AWS-java-sdk biblioteki Amazona, które zaczęły się nić IdleConnectionReaper ale nigdy wyłączania (Były com.amazonaws.services.ec2. AmazonEC2Client i com.amazonaws.services.cloudwatch. AmazonCloudWatchClient). Następnie dodałem metodę destroy() do tej klasy, która nazywa się statyczną metodą com.amazonaws.http.IdleConnectionReaper.shutdown(). Metoda destroy jest wywoływana, gdy klasa jest zbiorem śmieci i jest skonfigurowana za pomocą Spring applicationContext.xml. Zalety robienia tego w ten sposób polegają na tym, że działa on nawet w aplikacjach innych niż aplikacje sieciowe i eliminuje zamknięcie wątku z kontekstu sieci. Właściwe rozwiązanie polega na tym, że klasy z biblioteki amazon aws-java-sdk, które uruchamiają wątek IdleConnectionReaper, powinny je wyłączyć, ale nie - stąd ten błąd. Zobacz referencje i fragmenty kodu poniżej dla mojego rozwiązania:

applicationContext.xml

<bean id="YourBeanName" class="com.your.package.name.YourBeanName" destroy-method="destroy"> 
    <!-- other optional configuration goes here --> 
</bean> 

YourBeanName.java - (klasa, która tworzy obiekty wykraczająca Amazon)

public class YourBeanName { 

     // omitted code 

     public void destroy() { 
      com.amazonaws.http.IdleConnectionReaper.shutdown(); 
     } 

     // omitted code 

    } 

referencje:

Amazon forum - Shutting down IdleConnectionReaper
Spring docs - Customizing the nature of a bean

+0

Niezła, dobra odpowiedź. – bobmarksie

+0

Używanie Tomcat + Spring. Dokładnie rozwiązanie, którego szukałem, aby rozwiązać przyczynę tego komunikatu o błędzie. – Joseph

2

Na szczycie odpowiedź Stuart (i zakładając używasz wiosna), co stanowi alternatywnie, jeśli nie używasz plików konfiguracyjnych XML:

@Component 
public class MyBean { 

// ... 

    @PreDestroy 
    private void cleanUp() { 
     try { 
      // Shutting down AWS IdleConnectionReaper thread... 
      com.amazonaws.http.IdleConnectionReaper.shutdown(); 
     } catch (Throwable t) { 
      // log error 
     } 
    } 

} 

Dla mnie działa, gdy użyłem komponentu bean implementującego interfejs com.amazonaws.services.s3.AmazonS3.

Powiązane problemy