Boot4升后AMQP retry属性怎么改

升 Boot4 后,Spring AMQP 重试已从 Spring Retry 迁到 Spring Framework。本稿讲旧 RabbitRetryTemplateCustomizer 怎么认改名、怎么迁到 Template/Listener 两个 Customizer、怎么验,不写 Kafka jitter 或 CLASSIC loader。

同系列:Kafka retry 属性怎么改、CLASSIC 加载器怎么删、DevTools 热重载怎么开、endpoint 启用属性怎么改------一句对照,不写进本稿交付。

Boot4 升后 RabbitRetryTemplateCustomizer 为什么失效?

Spring Boot 4.0 Migration Guide · Spring AMQP Retry Features 写得很直:

Spring AMQP has moved its retry capabilities from Spring Retry to Spring Framework.

Spring Boot offers a customization hook-point for retry features used by the RetryTemplate and message listeners. To make it more explicit, two dedicated customizers have been introduced: RabbitTemplateRetrySettingsCustomizer, and RabbitListenerRetrySettingsCustomizer.

If you were using RabbitRetryTemplateCustomizer to customize the retry settings according to a target, you will need to migrate to either of those interfaces.

也就是说:不是 AMQP 重试能力被拿掉 ,而是实现底座从 Spring Retry 迁到 Spring Framework 后,Boot 把「按 Target 定制一份 RetryTemplate」拆成两个更明确的钩子------发模板一侧、监听一侧各一个。以前靠 RabbitRetryTemplateCustomizer(配合 Target.SENDER / Target.LISTENER)做定制的代码,升到 Boot4 后常见现象是:

现象 大致原因
编译找不到 RabbitRetryTemplateCustomizer / 旧包名 接口已由两个新 Customizer 替代
Bean 还在,但 retry 不再按旧分支生效 Guide:须迁到 Template / Listener 专用接口
只改了 YAML 里的 spring.rabbitmq.*.retry.*,自定义 Bean 未动 属性与 Customizer 是两层;本稿盯 Customizer 改名
误以为是 Kafka random→jitter 同一坑 不是(见后文分列)

API 落点(since 4.0.0):

本稿只盯 AMQP retry Customizer 怎么认改名、怎么迁、怎么与 Kafka retry 区分,其它 Boot4 主题见文首内链。

先过一张迁移总览图:

图:旧 RabbitRetryTemplateCustomizer → Boot4 迁到 Spring Framework → 拆成 Template / Listener 两接口 → 发送/监听重试冒烟。

旧写法长什么样(Boot3,勿再沿用)

Boot 3.x 常见做法是声明一个 RabbitRetryTemplateCustomizer Bean,在回调里按 Target 分支------SENDER 对应 RabbitTemplate,LISTENER 对应消息监听容器。旧包名在 org.springframework.boot.autoconfigure.amqp。

java 复制代码
package com.example.amqp;

import org.springframework.boot.autoconfigure.amqp.RabbitRetryTemplateCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;

/**
 * Boot 3.x 旧写法示意------升 Boot4 后请删除/替换。
 * 旧接口按 Target 定制同一份 org.springframework.retry.support.RetryTemplate。
 */
@Configuration
public class LegacyAmqpRetryConfig {

    @Bean
    RabbitRetryTemplateCustomizer legacyRabbitRetryTemplateCustomizer() {
        return (target, retryTemplate) -> {
            if (target == RabbitRetryTemplateCustomizer.Target.SENDER) {
                tune(retryTemplate, 3);
            } else if (target == RabbitRetryTemplateCustomizer.Target.LISTENER) {
                tune(retryTemplate, 5);
            }
        };
    }

    private static void tune(RetryTemplate retryTemplate, int maxAttempts) {
        SimpleRetryPolicy policy = new SimpleRetryPolicy();
        policy.setMaxAttempts(maxAttempts);
        retryTemplate.setRetryPolicy(policy);

        ExponentialBackOffPolicy backOff = new ExponentialBackOffPolicy();
        backOff.setInitialInterval(1000L);
        backOff.setMultiplier(2.0);
        backOff.setMaxInterval(10_000L);
        retryTemplate.setBackOffPolicy(backOff);
    }
}

升 Boot4 后这段的问题不在「重试次数设多少」,而在:接口与回调签名整条换了 。再继续实现 RabbitRetryTemplateCustomizer,要么编不过,要么 Bean 挂不上新的自动配置钩子。Guide 口径是 migrate to either of those interfaces------按场景拆,而不是找一个「同名兼容别名」。

新写法:Template 与 Listener 各一个 Customizer

包名也变了:新接口在 org.springframework.boot.amqp.autoconfigure。Template 侧回调参数是 RabbitRetryTemplateSettings;Listener 侧直接是 RetryPolicySettings(org.springframework.boot.retry)。两者都是 @FunctionalInterface,可以用 lambda。

发模板重试:RabbitTemplateRetrySettingsCustomizer

java 复制代码
package com.example.amqp;

import java.time.Duration;

import org.springframework.boot.amqp.autoconfigure.RabbitTemplateRetrySettingsCustomizer;
import org.springframework.boot.retry.RetryPolicySettings;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Boot 4:定制 RabbitTemplate 操作所用的 retry settings。
 * API:customize(RabbitRetryTemplateSettings) since 4.0.0
 */
@Configuration
public class AmqpTemplateRetryConfig {

    @Bean
    RabbitTemplateRetrySettingsCustomizer rabbitTemplateRetrySettingsCustomizer() {
        return retrySettings -> {
            RetryPolicySettings policy = retrySettings.getRetryPolicySettings();
            policy.setMaxRetries(3L);
            policy.setDelay(Duration.ofSeconds(1));
            policy.setMultiplier(2.0);
            policy.setMaxDelay(Duration.ofSeconds(10));
        };
    }
}

官方参考还写明:也可以通过配置属性打开模板重试,例如 spring.rabbitmq.template.retry.enabled=true;程序化定制则声明上述 Customizer Bean。属性开关注与 Customizer 互补,不要以为「只改 YAML 就等于迁完了旧 Bean」。

监听消费重试:RabbitListenerRetrySettingsCustomizer

java 复制代码
package com.example.amqp;

import java.time.Duration;

import org.springframework.boot.amqp.autoconfigure.RabbitListenerRetrySettingsCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Boot 4:定制 message listener 所用的 RetryPolicy settings。
 * API:customize(RetryPolicySettings) since 4.0.0
 */
@Configuration
public class AmqpListenerRetryConfig {

    @Bean
    RabbitListenerRetrySettingsCustomizer rabbitListenerRetrySettingsCustomizer() {
        return retrySettings -> {
            retrySettings.setMaxRetries(5L);
            retrySettings.setDelay(Duration.ofMillis(500));
            retrySettings.setMultiplier(2.0);
            retrySettings.setMaxDelay(Duration.ofSeconds(8));
        };
    }
}

Listener 侧重试默认同样是关的;官方文档说明可用配置打开,并可用本 Customizer 程序化改 RetryPolicy。耗尽后的 recover 行为(如 RejectAndDontRequeueRecoverer)属监听框架默认策略,本稿不展开成另一条主线------先把 Customizer 迁对。

选型对照(一张表记牢)

你以前在旧 Bean 里分支的 Target Boot4 应实现的接口 回调参数
Target.SENDER(RabbitTemplate) RabbitTemplateRetrySettingsCustomizer RabbitRetryTemplateSettings → 再 getRetryPolicySettings()
Target.LISTENER(监听容器) RabbitListenerRetrySettingsCustomizer RetryPolicySettings
两边都定制过 两个 Bean 都要,不要指望一个接口兼顾 分文件/分配置类更清晰

旧代码若是「一个 Customizer 里 if/else 两个 Target」,升版时拆成两个 @Bean 最不容易漏。只发消息、从不 @RabbitListener 的服务,可以只迁 Template 侧;纯消费服务则相反。

Template 和 Listener 该用哪个新 Customizer?

按调用栈症状选,不要按「类名里有没有 RetryTemplate」猜:

  1. 生产者 / 出站 :业务代码走 RabbitTemplate.convertAndSend(或 AmqpTemplate)失败后的自动重试 → Template Customizer;同时核对 spring.rabbitmq.template.retry.* 是否已启用。
  2. 消费者 / 入站 :@RabbitListener 方法抛异常后的投递重试 → Listener Customizer;核对 spring.rabbitmq.listener.simple.retry.*(或 direct 容器对应项)是否启用。
  3. 两边都有:两个 Bean 都注册;MR 描述里写清「SENDER→Template,LISTENER→Listener」,方便评审对照 Guide 原文。

不要把「监听重试次数」写进 Template Customizer 里指望两边生效------Boot4 拆接口的目的就是显式 。同样,也不要再引入已移除依赖管理路径上的 org.springframework.retry.support.RetryTemplate 去「手搓兼容层」当长期方案;Guide 对 Spring Retry 依赖管理移除是另一条说明,本稿只一句:若业务仍直连 Spring Retry,需显式版本 并考虑迁 Framework------不是本稿主线。

和 Kafka retry 的 random→jitter 是同一坑吗?

不是。 169145369《Boot4升后Kafka retry属性怎么改》 落在 Migration Guide 的 Spring Kafka Retry Features :配置键 spring.kafka.retry.topic.backoff.random removed in favor of ...backoff.jitter。那是 YAML/属性键替换。

本稿是 Spring AMQP Retry Features :Java 回调接口改名/拆分 (RabbitRetryTemplateCustomizer → 两个 *RetrySettingsCustomizer)。

维度 AMQP(本稿) Kafka(169145369)
Guide 小节 Spring AMQP Retry Features Spring Kafka Retry Features
变更形态 Customizer 接口拆分 配置键 random→jitter
典型症状 旧接口编不过 / Bean 不生效 旧键不绑定 / 告警
改法 迁到 Template 或 Listener Customizer 改写 jitter 属性
是否混判 勿混 勿混

两边都提到「retry 从 Spring Retry 迁到 Spring Framework」,但交付物完全不同 。升版评审拆两条 checklist:一条扫 RabbitRetryTemplateCustomizer,一条扫 backoff.random。绑同一个 MR 时,失败日志关键字也对不上号。

怎么快速核自己的 AMQP 配置 / Bean?

验收不要只看「应用能启」。Customizer 踩坑在类型迁移与钩子是否挂上,建议写成可勾选步骤:

图:对照 Guide → 搜旧 Customizer 残留 → 按场景迁两接口 → 模板发送/监听重试冒烟 → 边界(勿混 Kafka jitter / CLASSIC / DevTools)。

1. 对照官方源

打开 Migration Guide 的 Spring AMQP Retry Features,确认仍是「moved ... to Spring Framework」+ 两个 dedicated customizers +「migrate to either of those interfaces」。API 页核 since 4.0.0。

2. 搜残留并替换

  • 全仓搜 RabbitRetryTemplateCustomizer、RabbitRetryTemplateCustomizer.Target、Target.SENDER、Target.LISTENER(限定在 AMQP 配置类);
  • 旧 import org.springframework.boot.autoconfigure.amqp.RabbitRetryTemplateCustomizer 一律清掉;
  • 按上表改成 Template / Listener 新接口;不要留一个空的旧 Bean「占位」。

3. 本地冒烟(文字 checklist)

  1. 确认相关 spring.rabbitmq.template.retry.enabled / spring.rabbitmq.listener.*.retry.enabled 按环境打开(与你们现网策略一致);
  2. 模板路径 :故意触发一次可恢复失败(如短暂断连测试桩),观察是否按 Customizer 中的 maxRetries / delay 节奏重试;
  3. 监听路径 :@RabbitListener 内抛受控异常,确认重试次数与间隔符合 Listener Customizer;耗尽后进你们既定的 DLQ / reject 策略;
  4. 启动日志 / Actuator(若有)确认没有「找不到旧 Customizer 类型」一类错误;
  5. 对照:Guide 小节 + 新 Bean 生效,即本条升版项闭环。

4. 全文搜「假绿」残留

检查项 期望
无 RabbitRetryTemplateCustomizer 源码引用 通过
Template / Listener 新接口按场景注册 通过
与 Kafka backoff.random 清单 分列,勿同一行改完
父工程 / 公司 starter 是否仍导出旧类型 一并扫

和 CLASSIC / DevTools / endpoint 怎么区分?

主线不同,症状域也不同。

主题 你在排查什么 该看哪篇
AMQP Retry Customizer(本稿) 旧 RabbitRetryTemplateCustomizer 失效 本稿:迁两接口
Kafka retry 属性 backoff.random / jitter 169145369
CLASSIC loader 构建里 loaderImplementation=CLASSIC 169615117
DevTools Live Reload 浏览器不自动刷新 169536598
endpoint access Actuator 启用语义 169441413

实务口诀:

  • 报错 / 编译点名 RabbitRetryTemplateCustomizer → 本稿;
  • 配置键带 kafka...backoff.random/jitter → Kafka 专文;
  • 构建关键字 CLASSIC / loaderImplementation → CLASSIC 专文;
  • 现象在 热刷 / Actuator → 各走专文。

Session MongoDB 直持移除、Spring Retry dependency management removed (需显式版本 / 迁 Framework)都是 Guide 里的邻条,仅作 fallback 知晓:不是本稿交付范围,升版 runbook 可另立条目,勿塞进本 MR 主描述。

常见误判怎么排?

1. 以为「改个 YAML 就等于迁完 Customizer」

属性开关管「开不开重试」;旧 Java 钩子仍必须换成新接口。两层都要核。

2. 把 Kafka jitter 改法套到 AMQP

AMQP 这条不是换 random→jitter 键,而是换 Customizer 类型。分列。

3. 只迁了 Template,忘了 Listener(或相反)

对照旧代码里出现过的 Target 枚举;两边都用过就两个 Bean。

4. 继续依赖 org.springframework.retry.* 手写「兼容层」当永久方案

过渡可以,长期应按 Guide 迁到 Framework retry;依赖管理移除是邻条,另开任务。

5. 和 CLASSIC / DevTools / endpoint 绑同一 MR

症状域完全不同。分 MR,回滚更干净。

团队升版清单(AMQP · retry Customizer 条)

把下面几行贴进 Boot4 升版 runbook 的「消息 / AMQP」小节即可:

  1. Migration Guide 确认 Spring AMQP Retry Features 与两个新 Customizer;
  2. 全仓删除 / 替换 RabbitRetryTemplateCustomizer;
  3. Target.SENDER → RabbitTemplateRetrySettingsCustomizer;
  4. Target.LISTENER → RabbitListenerRetrySettingsCustomizer;
  5. 核对 spring.rabbitmq.template.retry.* / listener.*.retry.* 与 Bean 一致;
  6. 模板发送 + 监听抛错各冒烟一次;
  7. 注明:与 Kafka jitter(169145369)、CLASSIC(169615117)、DevTools(169536598)、endpoint(169441413)分列;

升版窗口怎么排期更稳?

建议把 AMQP Customizer 迁改单独成 MR:先对照 Guide 确认两个新接口,再全仓清 RabbitRetryTemplateCustomizer,最后才开模板/监听冒烟。父工程或公司 starter 若仍导出旧类型,要和业务侧一起扫,避免「业务已迁、starter 还编不过」。Kafka jitter、CLASSIC、DevTools、endpoint 各走专文 checklist,不要绑进同一回滚单元。

FAQ

Boot4 升后 RabbitRetryTemplateCustomizer 为什么失效?

Migration Guide:AMQP retry 已迁到 Spring Framework;须改用 RabbitTemplateRetrySettingsCustomizer 或 RabbitListenerRetrySettingsCustomizer。

Template 和 Listener 该用哪个新 Customizer?

发模板 / RabbitTemplate 侧重试用 Template;@RabbitListener 消费重试用 Listener;两边都定制过就两个都要。

和 Kafka retry 的 random→jitter 是同一坑吗?

不是。Kafka 是配置键替换;AMQP 是 Customizer 接口拆分。分列,勿混。

Spring Retry 依赖管理移除和这次 Customizer 改名是什么关系?

同属「retry 迁 Spring Framework」大背景;Customizer 改名是 AMQP 专用钩子调整。依赖管理移除(需显式版本)是邻条,不是本稿主线。

怎么快速核自己的 AMQP 配置 / Bean?

对照 Guide → 搜旧接口 → 按 Target 迁到新接口 → 打开对应 retry 开关 → 发送/监听各冒烟一次。

小结 checklist

  • 认清变更:AMQP retry 迁到 Spring Framework ;旧 RabbitRetryTemplateCustomizer 须替换
  • Template 侧:实现 RabbitTemplateRetrySettingsCustomizer(since 4.0.0)
  • Listener 侧:实现 RabbitListenerRetrySettingsCustomizer(since 4.0.0)
  • 旧 Target.SENDER / LISTENER 分支拆成两个 Bean(按需)
  • 对照源:Migration Guide · Spring AMQP Retry Features
  • 冒烟:模板发送重试 + 监听消费重试
  • 与 Kafka jitter(169145369)分列勿混
  • 勿抢 CLASSIC(169615117)/ DevTools(169536598)/ endpoint(169441413)
  • Session Mongo / Spring Retry BOM 仅邻条,非本稿主线

按「对照 Guide → 删旧 Customizer → 按场景挂两个新接口 → 发送/监听冒烟」改完,这类踩坑通常一次就能闭环。别在 Kafka jitter / CLASSIC 两侧来回猜。其它 Boot4 能力见前述内链,本文不展开。

相关推荐
ZealSinger19 小时前
Go1.27升后trace http怎么监听
go1.27·升级踩坑·go-tool-trace·http监听
ZealSinger2 天前
Go1.27升后GODEBUG旧值怎么处理
go1.27·升级踩坑·godebug·asynctimerchan
ZealSinger6 天前
Boot4升后Kafka retry属性怎么改
kafka·retry·boot4·升级踩坑
ZealSinger7 天前
Boot4升后session_redis属性怎么改名
redis·springsession·boot4·升级踩坑
ZealSinger12 天前
Boot4升后HttpServiceClient怎么换
boot4·httpservice·importhttp·升级踩坑
ZealSinger16 天前
Boot4升后WebClient starter怎么换
starter·webclient·restclient·boot4
ZealSinger21 天前
Boot4升级后MockBean和MockMvc怎么改
mockmvc·boot4·mockbean·mockitobean
做个文艺程序员23 天前
MQ第02篇:RabbitMQ快速上手教程:AMQP模型详解+Spring Boot整合实战(附完整代码)
spring boot·消息队列·rabbitmq·java-rabbitmq·amqp
乱七八糟的屋子3 个月前
AMQP C++ 超详细实战教程(amqp-cpp 开源库从零入门到生产落地)
c++·rabbitmq·任务队列·amqp·流量削峰·c++服务端异步解耦·分布式消息通信