AWS SQS死信队列-仅在某些情况下

时间:2018-10-24 11:26:29

标签: amazon-web-services spring-boot amazon-sqs dead-letter

我的问题不是很容易,但是我相信我会在您的帮助下找到解决我问题的方法。我有一个微服务,可从AWS SQS队列读取消息并将其保存在Redis中。

在AWS上,我有两个队列:

  1. AQueue(标准队列)
  2. DeadLetterQueue

我想:

  • 例如,在进行5次错误分析时,从我的标准队列(AQueue)中删除消息并将其移动到DeadLetterQueue
  • 例如,当我的Redis暂时不可用时,我不想删除当前已阅读的邮件。在这种情况下,应一遍又一遍地读取这些消息,直到Redis正常工作为止。

我该怎么做?在AWS上,我将我的标准队列(AQueue)设置为在消息将失败5次时将消息发送到DeadLetterQueue

我的听众:

@SqsListener(value = "${amazon.sqs.destination}", deletionPolicy = SqsMessageDeletionPolicy.NEVER)
    public void receive(String requestJSON, Acknowledgment acknowledgment) {
        try (Jedis jedis = jedisPool.getResource()) {
            if (redisPassword != null && !redisPassword.isEmpty()) {
                jedis.auth(redisPassword);
            }
            long key = jedis.incr("Trace:");
            Trace trace = Trace.fromJSON(requestJSON);
            trace.setTechnicalId(Long.toString(key));
            traceRepository.save(trace);
            acknowledgment.acknowledge();
        }catch (IOException e) {
            log.error("Parse error: " + e.getMessage());
            queueMessagingTemplate.convertAndSend(deadLetterQueue, requestJSON);
            acknowledgment.acknowledge();
        } catch(Exception e){
            log.error("Problem with NOSQL database Redis: " + e.getMessage());
        }

不幸的是,即使在5次尝试之后我都没打acknowledgment.acknowledge();,我的消息也转移到了DeadLetterQueue。

2 个答案:

答案 0 :(得分:0)

听起来您的逻辑已经颠倒了-不确认该消息将意味着它将被视为失败(并被重试,并最终移至死信队列)。想要将该消息标记为已使用时,请对其进行确认,如果要重试/ DLQ,请不要对其进行确认。

(注意-我不熟悉这里涉及的spring工具,但是我假设直接映射到核心SQS概念)

答案 1 :(得分:0)

逻辑应为:

  • 如果Redis处于关闭状态,请勿从SQS中提取消息(这会将它们保留在队列中)
  • 如果成功处理了一条消息,请使用提供的MessageHandle
  • 删除该消息
  • 配置队列以尝试5次处理后将邮件移至死信队列