2013-08-16 38 views
3

我有以下代碼從SQS隊列中檢索消息。我正在使用AmazonSQSBufferedAsyncClient從隊列中檢索消息。固定延遲SingleThreadedExecutor每5分鐘喚醒一次,呼叫receiveMessage。長輪詢在隊列SQS消息總是留在機上

@Service 
public class AmazonQueueService 
    implements QueueService<String> { 

    @Autowired 
    private AmazonSQSBufferedAsyncClient sqsAsyncClient; 

    @Value("${aws.sqs.queueUrl}") 
    private String queueUrl; 

    @Override 
    public List<Message<String>> receiveMessage() { 
     ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl); 
     ReceiveMessageResult result = sqsAsyncClient.receiveMessage(receiveMessageRequest); 

     LOG.debug("Size=" + result.getMessages().size()); 

     return Lists.transform(result.getMessages(), ......); 
    } 

    ..... 
} 

啓用的問題是當我檢查AWS控制檯,該消息始終在飛行,但它從來沒有在應用程序接收(大小總是打印爲0)。看起來AmazonSQSBufferedAsyncClient正在從隊列中讀取消息,但不會在receiveMessage調用中返回。

任何想法?

+0

了'AmazonSQSBufferedAsyncClient'如何配置(超時,線程等)?以及如何配置隊列,關於消息的可見性超時?或者,您是否在發送消息時指定了可見性超時? –

+0

剛剛發生的事情:您似乎正在使用某種依賴注入('@ Autowired')。你能否創建'AmazonSQSBufferedAsyncClient'的多個實例,而不是一個單一的實例,它是在你的類「AmazonQueueService」的所有實例之間共享的?如果是這樣的話,他們會爭取消息。你可以嘗試打印'AmazonSQSBufferedAsyncClient'的'.hashCode()'只是爲了確保您有一個實例... –

+0

林prettry確保只有AmazonSQSBufferedAsyncClient的'單個實例」。隊列屬性如下 – vijay

回答

3

終於想通了這一點。該問題表現爲隊列可見性超時(2分鐘)和計劃執行器延遲(5分鐘)的組合。

提高可見性超時15分鐘解決了這個問題。

我的理論是 - >的AmazonSQSBufferedAsyncClient檢索信息並保存到緩衝區等待receiveMessage電話。由於執行器延遲時間爲5分鐘,因此調用receiveMessage消息的可見性超時,並將消息返回隊列。它看起來像是幾乎立即從隊列中選取消息。現在無論出於什麼原因,對receiveMessage的調用都不會收到消息。我想,在超時事件發生之前,增加超時讓receiveMessage調用發生的機會得以解決。

任何其他可能的解釋?

1

你必須從隊列中刪除該郵件,當你用它做。如果你不這樣做,它會保持在飛行中,直到超時,然後直接返回隊列。它是這樣設計的,所以你永遠不會失去信息。如果程序在完成處理消息並刪除它之前崩潰,則消息將直接返回隊列。

從基本Java exampleSampleDriver.java):

QMessage message = messages.get(0); 

System.out.println("\nMessage received"); 
System.out.println(" message id:  " + message.getId()); 
System.out.println(" receipt handle: " + message.getReceiptHandle()); 
System.out.println(" message content: " + message.getContent()); 

testQueue.deleteMessage(message.getReceiptHandle()); // <===== here 
+0

是的。但刪除接收和處理消息後至少有一次,我沒有收到來自sqsAsyncClient.receiveMessage消息調用 – vijay

+1

啊。那麼,如果它在飛行中,這是客戶端的東西。要麼你有另一個客戶端收到消息,而不是刪除它,或者Java調用是錯誤的。你有沒有嘗試像Python [boto](https://github.com/boto/boto)等其他庫? – kichik