2013-08-05 6 views
10

Ich habe eine Webanwendung (mit Spring 3.1) die @ Scheduled Annotation für die regelmäßige Ausführung einer Worker-Task (geplante Verzögerung) verwendet. Die Worker-Aufgabe öffnet eine Verbindung zu AWS DynamoDb und führt einige DB-Lese-/Aktualisierungsvorgänge aus. Wenn ich die Webapp (von Tomcat-Manager) stoppe bekomme ich diese Nachricht in catalina.out:Spring MVC WebApp: @ Schedule: java-sdk-http-Verbindung-Reaper:

"SEVERE: Die Webanwendung [] scheint einen Thread mit dem Namen [java-sdk-http-connection-reaper] gestartet zu haben aber es ist nicht gelungen, das zu stoppen. Dies führt sehr wahrscheinlich zu einem Speicherleck. "

Ich habe das Gefühl, dass dies etwas mit meiner geplanten Aufgabe zu tun hat, auch nachdem Tomcat gestoppt hat.

@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(); 
     } 
      } 

} 

Dispatcher-servlet.xml:

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

Bin ich dies richtig tun? a) Ich starte den TaskScheduler nicht explizit. Also nehme ich an, der Frühling kümmert sich darum, diesen Service zu beginnen. Die 'this.myDbConn.shutdown()' wird aufgerufen. Trotzdem bekomme ich den Fehler. Ich benutze Spring MVC.

Antwort

12

Dies dürfte durch die AWS-Bibliothek verursacht wird, die einen Thread im Hintergrund com.amazonaws.http.IdleConnectionReaper

Sie können es heruntergefahren durch die Implementierung eines ServletContextListener es

beim Herunterfahren schließen
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 
    } 
} 
} 
genannt beginnt

und das Hinzufügen dieses zu Ihrem web.xml

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

Ich mag diese Antwort, obwohl unten funktionieren könnte. Da ich AWS SDK in einem anderen Glas konsumiere, dessen Inneres mir nicht bekannt ist. –

7

ich auch dieses Problem hatte, aber ich entschied sich für eine alternative Lösung zu @ David_Wartell der über.

ich die Klasse aufgespürt, die ein entsprechendes Objekt/Objekte von Amazon aws-java-sdk-Bibliothek wurde zu schaffen, den IdleConnectionReaper Thread wurden Anfahren aber nie heruntergefahren (diese waren com.amazonaws.services.ec2. AmazonEC2Client und com.amazonaws.services.cloudwatch. AmazonCloudWatchClient). Dann fügte ich dieser Klasse eine destroy() -Methode hinzu, die die statische Methode com.amazonaws.http.IdleConnectionReaper.shutdown() aufruft. Die Destroy-Methode wird aufgerufen, wenn die Klasse Garbage Collection erfasst wird und sie mit Spring applicationContext.xml konfiguriert wird. Die Vorteile dieser Vorgehensweise bestehen darin, dass sie auch für Nicht-Web-Anwendungen funktioniert und die Thread-Abschaltung von Ihrem Web-Kontext trennt. Die richtige Lösung ist, dass die Klassen aus der amazon aws-java-sdk-Bibliothek, die den IdleConnectionReaper-Thread starten, ihn herunterfahren sollten, aber das tun sie nicht - daher dieser Bug. Siehe Referenzen und Code-Schnipsel unten für meine Lösung:

applicationContext.xml

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

YourBeanName. java - (Klasse, die die beanstandeten amazon-Objekte erstellt)

public class YourBeanName { 

     // omitted code 

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

     // omitted code 

    } 

Referenzen:

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

+0

Schöne, gute Antwort. – bobmarksie

+0

Verwenden von Tomcat + Spring. Genau die Lösung, die ich suchte, um die Ursache dieser Fehlermeldung zu beheben. – Joseph

2

Oben Stuart Antwort (und vorausgesetzt, Sie sind mit Spring), eine Alternative, wenn Sie keine XML-Konfigurationsdateien verwenden:

@Component 
public class MyBean { 

// ... 

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

} 

Es hat für mich funktioniert, wenn ich eine Bean com.amazonaws.services.S3.AmazonS3 Schnittstelle verwendet.