我正在评估Spring,它正是新项目的生态系统。我希望我的应用程序对数千个不同客户端发送的UDP事件做出反应。每个客户端每5-10s发送1-10个UDP数据包。每个数据包将被并且应该被非常快速地处理(主要在内存和小型计算中,有助于redis,仅偶尔进行数据库调用)。不会向呼叫者返回数据。
我在Spring中实现了Reactor,就像他们在wiki上所描述的那样。 然后我实现了UDP入站通道,就像他们在Spring Integration文档中描述的那样。这是配置:
<int-ip:udp-inbound-channel-adapter id="receiverChannel"
channel="stringConvert"
port="9000"
multicast="false"
check-length="false"
pool-size="10"
lookup-host="false"
/>
<int:transformer id="convertChannel"
input-channel="stringConvert"
output-channel="toProcess"
ref="transformer"
method="transform"
/>
<int:service-activator input-channel="toProcess"
ref="accumulator"
method="accumulate"/>
<bean id="accumulator" class="hello.UDPAccumulator" />
<bean id="transformer" class="hello.UDPTransformer" />
然后在UDPAccumulator中我将该消息发布到reactor:
@Service
public class UDPAccumulator {
@Autowired
ReactorProducer producer;
public void accumulate(String quote) {
producer.fireEvent(quote);
}
}
这是否是“正确”的方式,关于我想要高吞吐量? int-ip:udp-inbound-channel-adapter 的内部工作原理是什么?它可以在将消息传递到反应堆之前成为瓶颈吗?我看到反应堆有一些TCP相关的类和支持,但没有UDP。任何有关如何以最好的方式做到这一点的建议表示赞赏!
奖金问题。如果消息的发送速度快于发送到反应堆的消息,该怎么办? redis message store(文章底部)会有帮助吗?如果我在反应堆中压缩这些数据包的方法很慢呢?
答案 0 :(得分:3)
由于我们尚未在Reactor中提供直接的UDP支持,因此将事件发布到Reactor的抽象是非常明智的。但是你在“奖金问题”中注意到发布商/消费者吞吐量存在问题,必须以特定领域的方式进行管理;那里没有银弹。
在您的使用案例中,我实际上很想说Processor
[1]可能更合适。它为数据处理提供了更高的总体吞吐量,因为它绕过了在普通Reactor
中发生的基于动态选择器的调度。除非您根据某些主题标准将传入事件分派给不同的处理程序,否则我建议您先查看。随着吞吐量的提高,您将不得不担心消费者跟不上(除非您的Consumer
做的事情非常缓慢,没有什么可以自动加速)。
但是,如果你真的,真的需要管理积压,我建议通过Queue
将你的生产者和消费者分开。 Reactor有一个PersistentQueue
[2]抽象,您可以使用JavaChronicle [3]将对象发布到磁盘并保存到磁盘,然后可以使用{{1}将其排入Consumer
(javadoc本周某个时候会出现Poller
,因为我们已经准备好了1.0 ...以前称之为Poller
[4])。
答案 1 :(得分:1)
我无法与Reactor对话,但UDP适配器有一个专用线程,可以读取原始数据包并将其移交给TaskExecutor
。它会尽快完成此操作,以便它可以返回读取下一个数据包。
默认TaskExecutor
是一个固定的线程池。
Reactor有DispatcherTaskExecutor
可以注入适配器。
相同的任务执行程序用于主读取器线程和切换。