Spring integration Spring集成AMQP-尽管有重试建议,仍会持续重试

Spring integration Spring集成AMQP-尽管有重试建议,仍会持续重试,spring-integration,spring-amqp,Spring Integration,Spring Amqp,我以前非常成功地使用了Spring与JMS的集成,但是我们现在使用RabbitMQ/AMQP,并且在错误处理方面存在一些问题 我有一个int amqp:inbound通道适配器,其中设置了一个errorChannel以接收任何异常,这里有一个ErrorTransformer类检查失败消息的原因异常。然后根据异常的类型:- 抑制异常并转换为JSON对象,该对象可以作为解释故障的业务回复转到AMQP出站通道适配器。在这里,我希望原始邮件已被消费/确认 或者重新抛出导致异常的异常,以让RabbitMQ

我以前非常成功地使用了Spring与JMS的集成,但是我们现在使用RabbitMQ/AMQP,并且在错误处理方面存在一些问题

我有一个int amqp:inbound通道适配器,其中设置了一个errorChannel以接收任何异常,这里有一个ErrorTransformer类检查失败消息的原因异常。然后根据异常的类型:-

  • 抑制异常并转换为JSON对象,该对象可以作为解释故障的业务回复转到AMQP出站通道适配器。在这里,我希望原始邮件已被消费/确认

  • 或者重新抛出导致异常的异常,以让RabbitMQ重新传递消息一定次数

  • 我发现重新抛出导致消息不断被重新传递,然后我阅读了关于StatefulRetryOperationsInterceptorFactoryBean的内容,因此添加了一个建议链以重试3次,然后我得到了关于没有消息id的异常,因此在建议链的开头添加了一个“MissingMessageIdAdvice”

    尽管有这样的建议,对于从errorChannel的ErrorTransformer重新抛出的RuntimeException,我仍然会不断地重试。我只是使用默认值通过RabbitMQ管理员发布消息。不确定是否缺少消息id导致此功能无法工作,如果是,如何使消息具有id? 我对以下两者之间的区别感到困惑:-

    A) ConditionalRejectingErrorHandler(我已经设置为入站适配器的错误处理程序),它允许我提供一个customFatalExceptionStrategy来实现isFatal()。其中我相信fatal=true(表示丢弃),消息被消费和丢弃,但我如何仍然发送出站失败消息

    B) 以及入站适配器上的errorChannel,我正在使用它检查异常并转换为出站失败响应消息。在这里,我想我可以抛出AmqpRejectAndDontRequeueException,但是为什么还要使用ConditionalRejectingErrorHandler呢?thorwing AMQP Rejected和Dont队列异常是否有效

         <int-amqp:inbound-channel-adapter id="amqpInRequestPatternValuation"  channel="requestAmqpIn" channel-transacted="true"  transaction-manager="transactionManager"
             queue-names="requestQueue" error-channel="patternValuationErrorChannel" connection-factory="connectionFactory"
             receive-timeout="59000" concurrent-consumers="1"
             advice-chain="retryChain" error-handler="customErrorHandler" />
    
     <bean id="customErrorHandler" class="org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler">
             <constructor-arg ref="customFatalExceptionStrategy"/>
      </bean>                             
    
    
    <bean id="customFatalExceptionStrategy" class="abc.common.CustomFatalExceptionStrategy"/>
    
    
    
      <!-- ADVICE CHAIN FOR CONTROLLING NUMBER OF RE-TRIES before sending to DLQ (or discarding if no DLQ) without this any re-queued fatal message will retry forever  -->
    
      <util:list id="retryChain">
          <bean class="org.springframework.amqp.rabbit.retry.MissingMessageIdAdvice">
              <constructor-arg>
                  <bean class="org.springframework.retry.policy.MapRetryContextCache" />
              </constructor-arg>
          </bean>
          <ref bean="retryInterceptor" />
      </util:list>
    
    <bean id="retryInterceptor"
        class="org.springframework.amqp.rabbit.config.StatefulRetryOperationsInterceptorFactoryBean">
        <property name="retryOperations" ref="retryTemplate" />
        <property name="messageRecoverer" ref="messageRecoverer"/>
    </bean>
    
     <bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
       <property name="retryPolicy" ref="simpleRetryPolicy" />
       <property name="backOffPolicy">
              <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
                     <property name="initialInterval" value="10000" />
              </bean>
       </property>
    </bean>
    
      <bean id="simpleRetryPolicy" class="org.springframework.retry.policy.SimpleRetryPolicy">
        <property name="maxAttempts" value="3" />
    </bean>
    

    您必须使用
    拒绝和dontrequeuerecoverer
    在重试结束时停止重新传递:

     * MessageRecover that causes the listener container to reject
     * the message without requeuing. This enables failed messages
     * to be sent to a Dead Letter Exchange/Queue, if the broker is
     * so configured.
    
    是的,
    messageId
    对于重试用例很重要


    如果在发送过程中无法手动提供消息,您可以插入自定义的
    MessageKeyGenerator
    策略来确定消息中的唯一密钥。

    我从来没有时间发布解决方案,所以它就在这里

    一旦我将重试建议链配置到AMQP入站通道适配器,该适配器必须包括RejectAndDontRequeueRecoverer的messageRecoverer(我认为也是dafault)。我缺少的重要一点是确保发件人发送消息时包含消息id。因此,如果通过RabbitMQ管理控制台发布,我需要包含预定义的消息id属性并提供一个值


    使用“MissingMessageIdAdvice”没有帮助(因此我删除了),因为它会在每次重新发送邮件时生成不同的邮件id,导致重试次数不会增加,因为每次发送都被认为与上次不同

    是,这很难处理您的主题。也许最好把它分成几个这样的问题?但是每个问题都是紧密相关的,所以我将非常感谢任何建议或解释。我已经将我的帖子简化为一个问题,并将发布另一个关于不同点的问题