SpringCloud 使用轮询的使用者
总览
使用轮询的使用者时,您可以按需轮询PollableMessageSource
。考虑以下受调查消费者的示例:
public interface PolledConsumer { @Input PollableMessageSource destIn(); @Output MessageChannel destOut(); }
给定上一个示例中的受调查消费者,您可以按以下方式使用它:
@Bean public ApplicationRunner poller(PollableMessageSource destIn, MessageChannel destOut) { return args -> { while (someCondition()) { try { if (!destIn.poll(m -> { String newPayload = ((String) m.getPayload()).toUpperCase(); destOut.send(new GenericMessage<>(newPayload)); })) { Thread.sleep(1000); } } catch (Exception e) { // handle failure } } }; }
PollableMessageSource.poll()
方法采用一个MessageHandler
参数(通常为lambda表达式,如此处所示)。如果收到并成功处理了消息,它将返回true
。
与消息驱动的使用者一样,如果MessageHandler
引发异常,消息将发布到错误通道,如“ ???”中所述。”。
通常,poll()
方法会在MessageHandler
退出时确认该消息。如果该方法异常退出,则该消息将被拒绝(不重新排队),但请参阅“处理错误”一节。您可以通过对确认负责来覆盖该行为,如以下示例所示:
@Bean public ApplicationRunner poller(PollableMessageSource dest1In, MessageChannel dest2Out) { return args -> { while (someCondition()) { if (!dest1In.poll(m -> { StaticMessageHeaderAccessor.getAcknowledgmentCallback(m).noAutoAck(); // e.g. hand off to another thread which can perform the ack // or acknowledge(Status.REQUEUE) })) { Thread.sleep(1000); } } }; }
您必须在某一时刻ack
(或nack
)消息,以避免资源泄漏。
某些消息传递系统(例如Apache Kafka)在日志中维护简单的偏移量。如果传递失败,并用StaticMessageHeaderAccessor.getAcknowledgmentCallback(m).acknowledge(Status.REQUEUE);
重新排队,则重新传递任何以后成功确认的消息。
还有一个重载的poll
方法,其定义如下:
poll(MessageHandler handler, ParameterizedTypeReference<?> type)
type
是一个转换提示,它允许转换传入的消息有效负载,如以下示例所示:
boolean result = pollableSource.poll(received -> { Map<String, Foo> payload = (Map<String, Foo>) received.getPayload(); ... }, new ParameterizedTypeReference<Map<String, Foo>>() {});
默认情况下,为可轮询源配置了一个错误通道。如果回调引发异常,则将ErrorMessage
发送到错误通道(<destination>.<group>.errors
);此错误通道也桥接到全局Spring Integration errorChannel
。
您可以使用@ServiceActivator
订阅任何一个错误通道来处理错误。如果没有订阅,则将仅记录错误并确认消息成功。如果错误通道服务激活器引发异常,则该消息将被拒绝(默认情况下),并且不会重新发送。如果服务激活器抛出RequeueCurrentMessageException
,则该消息将在代理处重新排队,并在随后的轮询中再次检索。
如果侦听器直接抛出RequeueCurrentMessageException
,则如上所述,该消息将重新排队,并且不会发送到错误通道。
更多建议: