it-swarm.com.de

Muster zum kontinuierlichen Abhören von AWS SQS-Nachrichten

Ich habe eine einfache Klasse namens QueueService mit einigen Methoden, die die Methoden vom AWS SQS SDK für Java umschließen. Zum Beispiel:

public ArrayList<Hashtable<String, String>> receiveMessages(String queueURL) {
        List<Message> messages = this.sqsClient.receiveMessage(queueURL).getMessages();

        ArrayList<Hashtable<String, String>> resultList = new ArrayList<Hashtable<String, String>>();
        for(Message message : messages) {
            Hashtable<String, String> resultItem = new Hashtable<String, String>();
            resultItem.put("MessageId", message.getMessageId());
            resultItem.put("ReceiptHandle", message.getReceiptHandle());
            resultItem.put("Body", message.getBody());
            resultList.add(resultItem);
        }
        return resultList;
    }

Ich habe eine andere Klasse namens App, die eine main hat und einen Instanz der QueueService erstellt. 

Ich suche nach einem "Muster", um die main in App zum Abhören neuer Nachrichten in der Warteschlange zu machen. Momentan habe ich eine while(true)-Schleife, in der ich die receiveMessages-Methode aufrufe:

while(true) {
            messages = queueService.receiveMessages(queueURL); 
            for(Hashtable<String, String> message: messages) {
                String receiptHandle = message.get("ReceiptHandle");
                String messageBody = message.get("MessageBody");
                System.out.println(messageBody);
                queueService.deleteMessage(queueURL, receiptHandle);
            }
        }

Ist das der richtige Weg? Soll ich die async-Nachrichtenempfangsmethode in SQS SDK verwenden?

5
Francisco Hanna

Meines Wissens gibt es in Amazon SQS keine Möglichkeit, ein aktives Listener-Modell zu unterstützen, bei dem Amazon SQS Nachrichten an Ihren Listener "pusht" oder Ihren Nachrichtenlistener bei Nachrichten aufruft.

Sie müssten also immer nach Nachrichten abfragen. Es werden zwei Abfragemechanismen unterstützt, die für das Abrufen unterstützt werden: Kurzes Abfragen und Langes Abfragen. Jeder hat seine eigenen Vor-und Nachteile, aber in den meisten Fällen würde Long Polling normalerweise verwendet, obwohl der Standard Short Polling ist. Der Mechanismus für lange Abfragen ist in Bezug auf den Netzwerkverkehr definitiv effizienter, kostengünstiger (weil Amazon Ihnen die Anzahl der gestellten Anfragen in Rechnung stellt) und der bevorzugte Mechanismus, wenn Sie möchten, dass Ihre Nachrichten zeitabhängig verarbeitet werden ( ~ = Prozess so schnell wie möglich).

Um Long Polling und Short Polling herum gibt es weitere Feinheiten, die es wert sind zu wissen, und es ist etwas schwierig, all das hier zu umschreiben. Wenn Sie möchten, können Sie jedoch im folgenden Blog weitere Einzelheiten lesen. Es gibt auch einige Codebeispiele, die hilfreich sein sollten.

http://pragmaticnotes.com/2017/11/20/Amazon-sqs-long-polling-versus-short-polling/

In Bezug auf eine (wahre) Schleife würde ich sagen, dass es darauf ankommt. Wenn Sie Long Polling verwenden und die Wartezeit auf (max.) 20 Sekunden einstellen können, werden SQS nicht öfter als 20 Sekunden abgefragt, wenn keine Nachrichten vorhanden sind. Wenn es Nachrichten gibt, können Sie entscheiden, ob Sie häufig abfragen (Nachrichten bearbeiten, sobald sie eintreffen) oder sie immer in Zeitintervallen (alle n Sekunden) verarbeiten.

Ein weiterer wichtiger Punkt wäre, dass Sie in einer einzigen receiveMessages-Anforderung bis zu 10 Nachrichten lesen könnten, wodurch sich auch die Anzahl der Anrufe, die Sie an SQS tätigen, verringert, wodurch die Kosten reduziert werden. Und wie das obige Blog ausführlich erläutert, können Sie 10 Nachrichten lesen, aber es werden möglicherweise nicht 10 zurückgegeben, auch wenn sich so viele Nachrichten in der Warteschlange befinden. 

Im Allgemeinen würde ich jedoch sagen, dass Sie geeignete Hooks und Ausnahmebehandlung erstellen müssen, um die Abfrage zu deaktivieren, wenn Sie dies zur Laufzeit wünschen, falls Sie eine (wahre) Struktur einer Weile verwenden.

Ein weiterer Aspekt, den Sie berücksichtigen sollten, ist, ob Sie SQS in Ihrem Hauptanwendungsthread abfragen möchten oder einen anderen Thread erstellen möchten. Eine andere Option könnte also darin bestehen, einen ScheduledThreadPoolExecutor mit einem einzelnen Thread im Main zu erstellen, um einen Thread so zu planen, dass das SQS regelmäßig (alle paar Sekunden) abgefragt wird. Möglicherweise benötigen Sie keine while-Struktur (true).

7
Amitkumar Gupta

Es gibt ein paar Dinge, die Sie vermissen:

  • Verwenden Sie receiveMessages(ReceiveMessageRequest) und legen Sie eine Wartezeit fest, um lange Abfragen zu ermöglichen.
  • Wickeln Sie Ihre AWS-Anrufe in try/catch-Blöcke ein. Achten Sie insbesondere auf OverLimitException, die von receiveMessages() ausgelöst werden kann, wenn Sie zu viele Nachrichten während des Fluges haben.
  • Wickeln Sie den gesamten Rumpf der while-Schleife in einen eigenen try/catch-Block ein, und protokollieren Sie alle Ausnahmen, die abgefangen werden (dies sollte nicht der Fall sein.) Hiermit wird sichergestellt, dass Ihre Anwendung nicht abstürzt, weil AWS ihre API geändert hat oder Sie nicht beachtet haben eine erwartete Ausnahme behandeln).

Weitere Informationen zu längeren Abfragen und möglichen Ausnahmen finden Sie unter doc .

Zur Verwendung des asynchronen Clients: Haben Sie einen bestimmten Grund, ihn zu verwenden? Wenn nicht, dann nicht: Ein einzelner Empfänger-Thread ist viel einfacher zu verwalten.

2
guest

Wenn Sie SQS und dann Lambda verwenden möchten, um die Anfrage zu verarbeiten, können Sie die in link angegebenen Schritte ausführen oder Sie verwenden immer Lambda anstelle von SQS und rufen für jede Anfrage Lambda auf. 

0
jpdave