本文介绍如何在 spring cloud aws 的 `@sqslistener` 中,仅对特定自定义异常(如 `mycustomexception`)触发消息重试,而对其他运行时异常静默处理或记录,避免意外丢消息或无限重试。核心在于结合
`on_success` 删除策略与显式异常捕获控制。
在使用 @SqsListener 消费 SQS 消息时,deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS 表示:仅当监听方法正常返回(无异常抛出)时,消息才被自动从队列中删除;一旦方法抛出任何未捕获的异常,SQS 将保留该消息,并在可见性超时后重新入队,从而触发重试。
但默认行为会导致 所有未捕获异常(包括 NullPointerException、IllegalArgumentException 等编程错误)均触发重试——这不仅违背业务语义(例如空指针不应重试),还可能掩盖真实缺陷,甚至因重复处理导致数据不一致。
✅ 正确做法是:主动捕获所有异常,仅将目标自定义异常重新抛出,其余异常吞掉或记录后静默忽略,确保只有业务明确标识的“可重试失败”才影响消息生命周期。
以下是推荐实现:
@SqsListener(
value = "https://sqs.us-east-1.amazonaws.com/123456789012/MyQueueURL",
deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS
)
public void getMessageFromSqs(MyMessage message) {
try {
log.info("Processing message: {}", message);
if (someCondition(message)) {
throw new MyCustomException("Business rule violated — retry needed");
}
// ✅ 业务逻辑成功执行,方法自然返回 → 消息被自动删除
log.info("Message processed successfully");
} catch (MyCustomException e) {
log.warn("Business-retryable failure occurred, letting SQS handle redelivery", e);
throw e; // ? 关键:仅重抛自定义异常,触发重试
} catch (Exception e) {
// ⚠️ 兜底捕获:记录非预期异常(如 NPE、IOE),但不抛出
log.error("Unexpected error (NOT retryable) — suppressing to avoid unintended redelivery", e);
// 不抛出 → 方法视为“成功完成” → 消息被删除(符合 ON_SUCCESS 语义)
}
}? 关键要点说明:
综上,通过「显式 try-catch + 精准重抛」,你能在保持 ON_SUCCESS 安全语义的同时,实现真正面向业务的弹性重试设计。