AWS SQS SDK for Javaのメソッドをラップするいくつかのメソッドを持つQueueService
という名前の単純なクラスがあります。例えば:
_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;
}
_
App
を持つmain
という名前の別のクラスがあり、QueueService
のインスタンスを作成します。
キュー内の新しいメッセージをリッスンするmain
内のApp
を作成する「パターン」を探しています。現在、receiveMessages
methodを呼び出すwhile(true)
ループがあります。
_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);
}
}
_
これは正しい方法ですか? SQS SDKで非同期メッセージ受信メソッドを使用する必要がありますか?
私の知る限り、Amazon SQSでは、Amazon SQSがリスナーにメッセージを「プッシュ」したり、メッセージがあるときにメッセージリスナーを呼び出したりするアクティブリスナーモデルをサポートする方法はありません。
したがって、常にメッセージをポーリングする必要があります。ポーリングでサポートされているポーリングメカニズムは、短期ポーリングと長期ポーリングの2つです。それぞれに長所と短所がありますが、ほとんどの場合、通常はロングポーリングが使用されますが、デフォルトはショートポーリングです。ロングポーリングメカニズムは、ネットワークトラフィックの点で間違いなくより効率的であり、コスト効率が高くなります(Amazonは行われたリクエストの数に応じて料金を請求するため)。 〜=できるだけ早く処理します)。
ロングポーリングとショートポーリングには、知る価値のある複雑な要素がありますが、ここですべてを言い換えることは多少困難ですが、必要に応じて、次のブログで詳細を読むことができます。役立つはずのコード例もいくつかあります。
http://pragmaticnotes.com/2017/11/20/Amazon-sqs-long-polling-versus-short-polling/
While(true)ループに関しては、それは依存すると言うでしょう。ロングポーリングを使用していて、待機時間を(最大)20秒に設定できる場合、メッセージがない場合は20秒より頻繁にSQSをポーリングしません。メッセージがある場合は、頻繁にポーリングするか(メッセージが到着したらすぐに処理するか)、または常に時間間隔で処理するか(たとえばn秒ごと)を決定できます。
もう1つの注意点は、1つのreceiveMessagesリクエストで最大10個のメッセージを読み取ることができるため、SQSへの呼び出し回数が減り、コストが削減されることです。また、上記のブログで詳細に説明しているように、10個のメッセージを読むようにリクエストすることもできますが、キューに多くのメッセージがある場合でも10個のメッセージを返さないことがあります。
ただし、一般的には、while(true)種類の構造を使用している場合は、実行時にポーリングをオフにするために適切なフックと例外処理を構築する必要があると思います。
考慮すべきもう1つの側面は、メインアプリケーションスレッドでSQSをポーリングするか、別のスレッドを生成するかです。したがって、別のオプションは、メインの単一スレッドでScheduledThreadPoolExecutorを作成して、スレッドを定期的(数秒ごと)にポーリングするようにスケジュールし、while(true)構造は必要ない場合があります。
不足していることがいくつかあります。
receiveMessages(ReceiveMessageRequest)
を使用し、待機時間を設定して長いポーリングを有効にします。OverLimitException
に注意してください。これは、処理中のメッセージが多すぎる場合にreceiveMessages()
からスローされる可能性があります。while
ループの本体全体を独自のtry/catchブロックでラップし、キャッチされた例外をログに記録します(あるべきではありません-これは、AWSが変更されたためにアプリケーションがクラッシュしないようにするためです。それらのAPIまたはあなたが予期される例外を処理することを怠った場合)。長いポーリングと考えられる例外の詳細については、 doc を参照してください。
非同期クライアントの使用に関して:使用する特別な理由はありますか?そうでない場合は、しないでください。単一のレシーバースレッドを管理する方がはるかに簡単です。
SQSを使用してからlambdaを使用してリクエストを処理する場合は、 link に記載されている手順に従うか、SQSの代わりに常にlambdaを使用して、リクエストごとにラムダを呼び出します。