我正在尝试配置以下流程:当消息到达Rabbit队列时尝试获取锁,向远程文件服务器查询一些文件,并为找到的每个文件向另一个队列发送新消息并释放锁发送完所有文件后。
IntegrationFlows.from(Amqp.inboundGateway(container)
.messageConverter(messageConverter)
)
.filter(m -> lockService.acquire())
.transform(m -> remoteFileTemplate.list(inputDirectory))
.split()
.handle(Amqp.outboundAdapter(amqpTemplate)
.exchangeName("")
.routingKey(routingKey)
.aggregate()
.handle(m -> {
log.info("Releasing lock");
lock.release();
})
.get();
问题是流程在第一个.handle
方法之后停止了(诚实地按预期),并且我无法弄清楚如何配置它以执行我想要的操作?我尝试使用.wireTap
和.publishSubscribeChannel
,但这使2个互不依赖的流,并且在文件实际发送之前释放了我的锁。
如果有人可以帮助我解释如何使用DSL修复它,那将非常好,因为我是动态创建这些流的...
我试图在频道上设置拦截器:
final DirectChannel channel = new DirectChannel();
channel.setInterceptors(Collections.singletonList(new ChannelInterceptor() {
@Override
public Message<?> preSend(final Message<?> message, final MessageChannel channel) {
lockService.acquire();
return message;
}
@Override
public void afterSendCompletion(final Message<?> message, final MessageChannel channel, final boolean sent, final Exception ex) {
lock.release();
}
}));
IntegrationFlows.from(Amqp.inboundGateway(container)
.messageConverter(messageConverter)
)
.channel(channel)
.transform(m -> remoteFileTemplate.list(inputDirectory))
.split()
.handle(Amqp.outboundAdapter(amqpTemplate)
.exchangeName("")
.routingKey(routingKey)
.get();
但是通过这种方式,获取,释放锁,然后才获取消息。我在做什么错了?
从Gitter聊天的帮助中找出来,以防其他人被卡住:
IntegrationFlows.from(Amqp.inboundGateway(container)
.messageConverter(messageConverter)
)
.channel(MessageChannels.direct().interceptor(new ChannelInterceptor() {
@Override
public Message<?> preSend(final Message<?> message, final MessageChannel channel) {
lockService.acquire();
return message;
}
@Override
public void afterSendCompletion(final Message<?> message, final MessageChannel channel, final boolean sent, final Exception ex) {
lockService.release();
}
}))
.transform(m -> remoteFileTemplate.list(inputDirectory))
.split()
.handle(Amqp.outboundAdapter(amqpTemplate)
.exchangeName("")
.routingKey(routingKey)
.get());
答案 0 :(得分:1)
在拆分后发布/订阅,在一个子流上使用AMQP处理程序,在另一个子流上使用聚合器,就可以了。
每个线程将在同一线程上被连续调用,最后一条消息又导致从聚合器释放,再次在同一线程上。
话虽如此,您将需要在入站网关上执行一些errorChannel处理,以在发生错误的情况下释放锁。
编辑
一种不太复杂的解决方案是在转换之前在通道上使用自定义ChannelInterceptor
而不是过滤器,以将锁锁定在preSend()
中并在afterSendCompleted()
中释放(称为无论成功还是失败)。