如何组织 Spring 方法的集成重试,其列表随每次重试而减少?
How to organize Spring Integration retry for a method with a list that decreases with every retry?
有以下 Spring 带重试的集成配置:
<int:chain input-channel="sdCreationChannel" output-channel="debugLogger">
<int:poller fixed-delay="500" />
<int:filter ref="sdIntegrationExistingRequestSentFilter" method="filter"/>
<int:service-activator ref="sdCreationServiceImpl" method="processMessage">
<int:request-handler-advice-chain>
<ref bean="retryAdvice"/>
</int:request-handler-advice-chain>
</int:service-activator>
</int:chain>
<bean id="retryAdvice" class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice" >
<property name="retryTemplate">
<bean class="org.springframework.retry.support.RetryTemplate">
<property name="backOffPolicy">
<bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
<property name="initialInterval" value="${integration.retry.initial.delay}"/>
<property name="multiplier" value="${integration.retry.backoff.multiplier}"/>
</bean>
</property>
<property name="retryPolicy">
<bean class="org.springframework.retry.policy.SimpleRetryPolicy">
<property name="maxAttempts" value="${integration.retry.max.attempts}" />
</bean>
</property>
</bean>
</property>
</bean>
简化后的Java代码如下:
@Component("sdCreationServiceImpl")
public class SDCreationServiceImpl implements SDCreationService {
@Autowired
private NotifySD notifySD;
@Override
public void processMessage(IntegrationPayload integrationPayload) {
List<ConfirmationCode> sdConfCodes = findCodesFromPayLoad(integrationPayload);
notifySD.activateConfirmationCodes(sdConfCodes);
}
重试此代码的问题在于,List sdConfCodes 可以在每次重试时被部分处理,因此每次我们需要发送以处理较少数量的元素。组织此代码的最佳方式是什么?
按照 Artem Bilan 的建议(谢谢!)我在 SDCreationServiceImpl 中创建了带有变量列表的第二个方法,即 activateConfirmationCodes,然后在 XML 规范中将此方法指向 sdCreationServiceImpl 的方法。
@Component("sdCreationServiceImpl")
public class SDCreationServiceImpl implements SDCreationService {
@Autowired
private NotifySD notifySD;
List<ConfirmationCode> sdConfCodes = new ArrayList<ConfirmationCode()>;
@Override
public void processMessage(IntegrationPayload integrationPayload) {
sdConfCodes = findCodesFromPayLoad(integrationPayload);
}
public void activateConfirmationCodes()
{
notifySD.activateConfirmationCodes(sdConfCodes);
}
然后 XML service-activator 规范如下:
<int:service-activator ref="sdCreationServiceImpl" method="activateConfirmationCodes">
<int:request-handler-advice-chain>
<ref bean="retryAdvice"/>
</int:request-handler-advice-chain>
</int:service-activator>
是的,这个方法 activateConfirmationCodes 在重试中被调用,但是第一个方法 processMessage 根本没有被调用。 是否可以指定一种方法用于第一次尝试调用而另一种方法用于重试?
其次,通过这种设计,列表变成了单例,这会给多线程带来问题,对吗?此列表是否可以仅针对特定消息与 bean 相关联?
从大的角度看,你的问题出在哪里还不清楚。从另外一方面来说说我的一些想法,或许我会猜到你的目标。
将 List<ConfirmationCode>
作为 payload
允许我们随时修改它。所以,让我们假设我们有 list 作为 10
元素。在第一次尝试中,我们处理了其中的 3 个。第四个失败了。我们必须去重试抛出一些适当的异常。
但是我们回到 retry-aware 方法的开头,所以参数相同。如果我们从集合中删除那些成功的项目,下一次重试迭代将根本不会处理它们。
从一方面可以实现区分 findCodesFromPayLoad()
服务和 activateConfirmationCodes()
,对最后一个应用重试。
从另一侧,您可以将 activateConfirmationCodes()
中的项目标记为已处理,因此下一个 findCodesFromPayLoad(integrationPayload)
不会 return 它们。
换句话说,有足够多的方法可以在不更改消息的情况下修改集合。
有以下 Spring 带重试的集成配置:
<int:chain input-channel="sdCreationChannel" output-channel="debugLogger">
<int:poller fixed-delay="500" />
<int:filter ref="sdIntegrationExistingRequestSentFilter" method="filter"/>
<int:service-activator ref="sdCreationServiceImpl" method="processMessage">
<int:request-handler-advice-chain>
<ref bean="retryAdvice"/>
</int:request-handler-advice-chain>
</int:service-activator>
</int:chain>
<bean id="retryAdvice" class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice" >
<property name="retryTemplate">
<bean class="org.springframework.retry.support.RetryTemplate">
<property name="backOffPolicy">
<bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
<property name="initialInterval" value="${integration.retry.initial.delay}"/>
<property name="multiplier" value="${integration.retry.backoff.multiplier}"/>
</bean>
</property>
<property name="retryPolicy">
<bean class="org.springframework.retry.policy.SimpleRetryPolicy">
<property name="maxAttempts" value="${integration.retry.max.attempts}" />
</bean>
</property>
</bean>
</property>
</bean>
简化后的Java代码如下:
@Component("sdCreationServiceImpl")
public class SDCreationServiceImpl implements SDCreationService {
@Autowired
private NotifySD notifySD;
@Override
public void processMessage(IntegrationPayload integrationPayload) {
List<ConfirmationCode> sdConfCodes = findCodesFromPayLoad(integrationPayload);
notifySD.activateConfirmationCodes(sdConfCodes);
}
重试此代码的问题在于,List sdConfCodes 可以在每次重试时被部分处理,因此每次我们需要发送以处理较少数量的元素。组织此代码的最佳方式是什么?
按照 Artem Bilan 的建议(谢谢!)我在 SDCreationServiceImpl 中创建了带有变量列表的第二个方法,即 activateConfirmationCodes,然后在 XML 规范中将此方法指向 sdCreationServiceImpl 的方法。
@Component("sdCreationServiceImpl")
public class SDCreationServiceImpl implements SDCreationService {
@Autowired
private NotifySD notifySD;
List<ConfirmationCode> sdConfCodes = new ArrayList<ConfirmationCode()>;
@Override
public void processMessage(IntegrationPayload integrationPayload) {
sdConfCodes = findCodesFromPayLoad(integrationPayload);
}
public void activateConfirmationCodes()
{
notifySD.activateConfirmationCodes(sdConfCodes);
}
然后 XML service-activator 规范如下:
<int:service-activator ref="sdCreationServiceImpl" method="activateConfirmationCodes">
<int:request-handler-advice-chain>
<ref bean="retryAdvice"/>
</int:request-handler-advice-chain>
</int:service-activator>
是的,这个方法 activateConfirmationCodes 在重试中被调用,但是第一个方法 processMessage 根本没有被调用。 是否可以指定一种方法用于第一次尝试调用而另一种方法用于重试? 其次,通过这种设计,列表变成了单例,这会给多线程带来问题,对吗?此列表是否可以仅针对特定消息与 bean 相关联?
从大的角度看,你的问题出在哪里还不清楚。从另外一方面来说说我的一些想法,或许我会猜到你的目标。
将 List<ConfirmationCode>
作为 payload
允许我们随时修改它。所以,让我们假设我们有 list 作为 10
元素。在第一次尝试中,我们处理了其中的 3 个。第四个失败了。我们必须去重试抛出一些适当的异常。
但是我们回到 retry-aware 方法的开头,所以参数相同。如果我们从集合中删除那些成功的项目,下一次重试迭代将根本不会处理它们。
从一方面可以实现区分 findCodesFromPayLoad()
服务和 activateConfirmationCodes()
,对最后一个应用重试。
从另一侧,您可以将 activateConfirmationCodes()
中的项目标记为已处理,因此下一个 findCodesFromPayLoad(integrationPayload)
不会 return 它们。
换句话说,有足够多的方法可以在不更改消息的情况下修改集合。