2014-01-06 10 views
5

Wir haben einen Java-Webdienst, der eine AWS SQS-Warteschlange für Nachrichten abfragt. Es verwendet die maximale Wartezeit von 20 Sekunden. Wenn der Dienst in Tomcat aktualisiert wird, versucht Tomcat, den vorhandenen Dienst zu beenden und startet dann die aktualisierte Version. Wenn das passiert, wenn die Warteschlange gelesen wird, bleibt der Thread stecken und Tomcat kann es nicht stoppen, was zu einem Speicherverlust führt. Nach meinem Experimentieren tritt dieser Speicherverlust nur auf, wenn Tomcat versucht, den Dienst zu stoppen, während er in der Warteschlange wartet.So beenden Sie SQS lesen Sie Java SDK

Wie kann ich eine SQS-Warteschlange während des Herunterfahrens in Java stoppen?

Hier sind einige weitere Details.

Jan 03, 2014 7:52:52 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads 
SEVERE: The web application appears to have started a thread named [pollSQSQueue-1] but has failed to stop it. This is very likely to create a memory leak. 
Jan 03, 2014 7:52:52 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks 
SEVERE: The web application created a ThreadLocal with key of type [com.amazonaws.auth.AWS4Signer$2] (value [[email protected]]) and a value of type [java.text.SimpleDateFormat] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
Jan 03, 2014 7:52:52 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks 
SEVERE: The web application created a ThreadLocal with key of type [com.amazonaws.auth.AWS4Signer$1] (value [[email protected]]) and a value of type [java.text.SimpleDateFormat] (value [[email protected]]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 

Der Dienst verwendet Spring und verwendet einen Spring-Scheduler, um den Abfrageprozess zu starten.

<task:scheduler id="pollSQSQueue" pool-size="1"/> 

Ich habe versucht, ApplicationListener<ContextClosedEvent> eine Feder zu schaffen, um zu versuchen, die Warteschlange zu Herunterfahren. Mein erster Versuch war, zu versuchen, die Warteschlange herunterzufahren und zu sehen, ob sie es anmutig gehandhabt hat. Es hat nicht.

@Override 
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) 
{ 
    amazonSQS.shutdown(); 
} 

Das nächste, was ich versuchte, die AmazonSQSAsync zu verwenden und ein asynchrones abrufen verwenden. Ich habe dann die Future<ReceiveMessageResult> erhalten und versucht, cancel darauf während der Federabschaltung zu rufen. Dies wurde auch nicht sehr anmutig behandelt.


Auch ich bin der IdleConnectionReaper der Notwendigkeit zur Abschaltung bewusst und dies tun, wenn Frühling heruntergefahren wird, so dass ich glaube, es nicht zu, dass in Zusammenhang steht.

+0

Ich habe die gleichen Probleme. Hast du eine Lösung gefunden? – Aliza

+0

Nein, ich habe keine Lösung gefunden. –

+0

Was verwenden Sie, um von SQS zu lesen? Ich meine, der Thread ist eine Klasse von dir? Können Sie den Code posten? –

Antwort

1

Sie können einen separaten Thread für die Abfrage erstellen. Etwas in dieser Richtung:

class MyService extends/implements ... { 
    private SQSPollingThread pollingThread; 

    //this is just my guess of what the "service start" method looks like 
    @Override 
    public void onApplicationEvent(ContextStartedEvent contextStartedEvent) 
    { 
     pollingThread = new SQSPollingThread(); 
     pollingThread.start(); 
    } 

    @Override 
    public void onApplicationEvent(ContextClosedEvent contextClosedEvent) 
    { 
     pollingThread.stop(); 
    } 
} 

class SQSPollingThread implements Runnable() { 
    private volatile boolean stopped = false; 

    public void stop() { 
     stopped = true; 
    } 

    @Override 
    public void run() { 
     while (!stopped) { 
      message = pollSqsBlockingFor20seconds(); 
      process(message); 
     } 
    } 
} 

Mit diesem Setup, wenn TomCat „sagt“ Ihren Dienst zu beenden, Ihr Dienst wird die gestoppte-Flag gesetzt und sofort zurück. Es kann immer noch eine Abrufanfrage ausstehen, die innerhalb der nächsten 20 Sekunden endet und verarbeitet wird. Nachdem dieses letzte Ereignis verarbeitet wurde, wird auch der innere SQSPollingThread beendet.

+1

Noch besser, Sie sollten in der Lage sein, den Thread zu unterbrechen, der die Abfrage durchführt, damit Sie nicht auf die 20-Sekunden-Umfrage warten müssen. Stellen Sie nur sicher, dass Sie den Interrupt nicht verschlucken/ignorieren. – Krease