You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置JMS容器工厂实现退避重试且不重试MessageConversionException

问题解答

问题1:指数退避重试配置不生效

你的ExponentialBackOffWithMaxRetries未生效的核心原因是Spring JMS的DefaultJmsListenerContainerFactory需要结合RetryTemplate才能启用自定义重试退避策略,单纯调用setBackOff()无法触发指数退避逻辑,默认会使用内置的SimpleRetryPolicy(默认10次重试、间隔1秒)。此外,configurer.configure(factory, connectionFactory)会应用Spring Boot自动配置,可能覆盖你提前设置的重试属性,需调整配置顺序。

修复代码

@Bean
fun jmsListenerContainerFactory(
    connectionFactory: ConnectionFactory,
    configurer: DefaultJmsListenerContainerFactoryConfigurer
): JmsListenerContainerFactory<*> {
    val factory = DefaultJmsListenerContainerFactory()
    // 先执行自动配置,再覆盖自定义重试规则
    configurer.configure(factory, connectionFactory)

    // 配置指数退避策略
    val backOffPolicy = ExponentialBackOffWithMaxRetries(5).apply {
        initialInterval = 1000
        maxInterval = 10000
        multiplier = 1.5
    }

    // 配置重试模板,关联重试次数与退避策略
    val retryTemplate = RetryTemplate().apply {
        setRetryPolicy(SimpleRetryPolicy(5))
        setBackOffPolicy(backOffPolicy)
    }

    factory.setRetryTemplate(retryTemplate)
    factory.setErrorHandler(ContainerFactoryErrorHandler())

    return factory
}

注意:如果使用Azure Service Bus JMS,部分重试行为可能由服务端策略控制,需确保客户端未启用服务端重试(可通过Azure配置调整)。

问题2:捕获无效JSON消息并阻止重试

该需求完全可行,但需调整逻辑:MessageConversionException发生在监听器方法调用前的消息转换阶段,容器会优先触发重试逻辑,再调用ErrorHandler。仅在ErrorHandler中不抛出异常无法阻止重试,需在重试策略中排除该异常类型,让容器直接跳过重试进入错误处理。

修复方案

  1. 调整重试策略,排除MessageConversionException
val retryPolicy = SimpleRetryPolicy().apply {
    // 仅允许RuntimeException触发重试
    val retryableExceptions = mapOf(
        RuntimeException::class.java to true
    )
    setRetryableExceptions(retryableExceptions)
}

val retryTemplate = RetryTemplate().apply {
    setRetryPolicy(retryPolicy)
    setBackOffPolicy(backOffPolicy)
}
  1. 保留ContainerFactoryErrorHandler逻辑,处理无效消息
class ContainerFactoryErrorHandler : ErrorHandler {
    private val logger = LoggerFactory.getLogger(javaClass)

    override fun handleError(t: Throwable) {
        when {
            t.cause is MessageConversionException -> {
                logger.error("无效JSON消息,已丢弃", t)
                // 不抛出异常,终止重试流程
            }
            else -> {
                // 重新抛出异常,触发重试(符合重试策略的情况)
                throw t
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Wall-E

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:24:55