我是Spring Integration的新手,并编写了一个示例,将消息从单个通道发送到多个通道,在此透视图中,为每个通道使用Redis消息存储,目的是不丢失任何消息。要求是向频道发送消息 - replyChannel,mailChannel和dbChannel。目前,代码只打印sysout语句,没有主要功能。
为了检查消息是否正确路由,我编写了一个java测试类来发送15条消息。
检查输出我发现有些消息丢失了。此外,没有任何例外情况正在显示。
感谢您的支持。
@Bean
public MessageChannel replyQueueChannel () { return new QueueChannel (new MessageGroupQueue(redisMesageStore(),replyQueue, 1000)); }
@Bean
public MessageChannel mailQueueChannel () { return new QueueChannel (new MessageGroupQueue(redisMesageStore(),mailQueue, 1000)); }
@Bean
public MessageChannel auditlogQueueChannel () { return new QueueChannel (new MessageGroupQueue(redisMesageStore(),auditLogQueue, 1000)); }
@Override
@ServiceActivator (inputChannel="dbQueueChannel", poller =@Poller(fixedDelay="10", taskExecutor="dbServiceExecutor"))
public void executeDBConditions (Message<DeferredModel> deferredMsg) {
replyQueueChannel.send(deferredMsg);
auditlogQueueChannel.send(deferredMsg);
mailQueueChannel.send (deferredMsg);
}
答案 0 :(得分:0)
第一步始终是为org.springframework
启用DEBUG日志记录;您将看到许多显示消息流的调试消息。
您还可以使用redis-cli
和monitor
命令监控redis以跟踪redis活动。
如果您无法弄清楚使用这些技术发生了什么,请将日志发布到github gist或pastebin等地方。
修改强>
这是您的方案的工作版本;我对“丢失的消息”没有任何问题。由于您没有显示完整的申请表,我不知道您为什么遇到麻烦。
我还使用在Java中配置的RecipientListRouter
添加了一个版本 - 但你真的应该将其作为一个新问题而不是捎带在这个问题上......
package com.example;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.redis.store.RedisChannelMessageStore;
import org.springframework.integration.store.MessageGroupQueue;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.PollableChannel;
import org.springframework.util.Assert;
@SpringBootApplication
public class So34628789Application {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(So34628789Application.class, args);
MessageChannel foo = context.getBean("foo", MessageChannel.class);
for (int i = 0; i < 15; i++) {
foo.send(MessageBuilder.withPayload("foo" + i).build());
}
getOutput(context);
// now with an RLR...
foo = context.getBean("routedMessageChannel", MessageChannel.class);
for (int i = 0; i < 15; i++) {
foo.send(MessageBuilder.withPayload("foo" + (i + 15)).build());
}
getOutput(context);
context.close();
}
private static void getOutput(ConfigurableApplicationContext context) {
int n = 0;
PollableChannel out = context.getBean("replyQueueChannel", PollableChannel.class);
for (int i = 0; i < 15; i++) {
Message<?> received = out.receive(10000);
if (received != null) {
System.out.println(received);
n++;
}
}
out = context.getBean("mailQueueChannel", PollableChannel.class);
for (int i = 0; i < 15; i++) {
Message<?> received = out.receive(10000);
if (received != null) {
System.out.println(received);
n++;
}
}
out = context.getBean("auditlogQueueChannel", PollableChannel.class);
for (int i = 0; i < 15; i++) {
Message<?> received = out.receive(10000);
if (received != null) {
System.out.println(received);
n++;
}
}
Assert.state(n == 45, "expected 45 messages");
}
@Autowired
private JedisConnectionFactory connectionFactory;
@Bean
public MessageChannel replyQueueChannel() {
return new QueueChannel(new MessageGroupQueue(redisMessageStore(), "replyQueue", 1000));
}
@Bean
public MessageChannel mailQueueChannel() {
return new QueueChannel(new MessageGroupQueue(redisMessageStore(), "mailQueue", 1000));
}
@Bean
public MessageChannel auditlogQueueChannel() {
return new QueueChannel(new MessageGroupQueue(redisMessageStore(), "auditLogQueue", 1000));
}
@Bean
public RedisChannelMessageStore redisMessageStore() {
return new RedisChannelMessageStore(connectionFactory);
}
@Bean
public MessageChannel foo() {
return new DirectChannel();
}
@Bean
public Foo fooService() {
return new Foo();
}
@Bean
public MessageChannel routedMessageChannel() {
return new DirectChannel();
}
// Router Technique 1
// @Bean
// @ServiceActivator(inputChannel="routedMessageChannel")
// public RecipientListRouter router() {
// RecipientListRouter router = new RecipientListRouter();
// List<Recipient> recipients = new ArrayList<>();
// recipients.add(new Recipient(replyQueueChannel()));
// recipients.add(new Recipient(mailQueueChannel()));
// recipients.add(new Recipient(auditlogQueueChannel()));
// router.setRecipients(recipients);
// return router;
// }
@MessageEndpoint
public static class Foo {
@Autowired
private MessageChannel replyQueueChannel;
@Autowired
private MessageChannel mailQueueChannel;
@Autowired
private MessageChannel auditlogQueueChannel;
private List<MessageChannel> channels;
@ServiceActivator(inputChannel="foo")
public void sendIt(Message<String> deferredMsg) {
replyQueueChannel.send(deferredMsg);
auditlogQueueChannel.send(deferredMsg);
mailQueueChannel.send (deferredMsg);
}
// Router Technique 2
@Router(inputChannel="routedMessageChannel")
public List<MessageChannel> route(Message<?> message) {
if (this.channels == null) {
this.channels = Arrays.asList(new MessageChannel[] { this.replyQueueChannel, this.mailQueueChannel,
this.auditlogQueueChannel });
}
return this.channels;
}
}
}
<强> EDIT2 强>
在Java配置中创建路由器有两种技术。
使用XML声明的端点创建2个bean - 消息处理程序和使用者。使用JavaConfig时,任何MessageHandler
@Bean
都可以使用@ServiceActivator
进行注释,以创建相应的使用者。
或者,您可以使用注释为@Router
的POJO方法。
我已更新上面的示例以显示其他技术。再一次,它对我来说很好。
您可以找到完整的项目on github here。
正如我所说,如果你丢失消息,你应该使用调试日志记录以及redis-cli
monitor命令来弄清楚发生了什么。