【发布时间】:2012-02-01 19:39:38
【问题描述】:
新手在使用 Netty 3.2.4 处理 UDP 视频流时遇到问题。在不同的机器上,我们看到使用 Netty 丢弃的字节等。在 Netty 获取字节后,我们有一个小计数器,以查看接收了多少字节。差异不仅仅是 UDP 不可靠性的原因。在我们的例子中,我们还将字节保存到文件中以播放视频。在 VLC 中播放视频确实说明了丢弃的字节。 (发送的数据包大小约为 1000 字节)。
问题
- 在不能将 AdaptiveReceiveBufferSizePredictor 用于 UDP 流侦听器方面,我们对 Netty API 的假设是否正确?
- 对我们看到的行为有更好的解释吗?
- 有更好的解决方案吗?有没有办法在 UDP 中使用自适应预测器?
我们的尝试
...
DatagramChannelFactory datagramChannelFactory = new OioDatagramChannelFactory(
Executors.newCachedThreadPool());
connectionlessBootstrap = new ConnectionlessBootstrap(datagramChannelFactory);
...
datagramChannel = (DatagramChannel) connectionlessBootstrap.bind(new
InetSocketAddress(multicastPort));
datagramChannel.getConfig().setReceiveBufferSizePredictor(new
FixedReceiveBufferSizePredictor(2*1024*1024));
...
根据文档和 Google 搜索,我认为正确的方法是使用 OioDatagramChannelFactory 而不是 NioDatagramChannelFactory。
此外,虽然我找不到明确说明,但您只能将 FixedReceiveBufferSizePredictor 与 OioDatagramChannelFactory 一起使用(与 AdaptiveReceiveBufferSizePredictor 相比)。我们通过查看源代码发现了这一点,并意识到 AdaptiveReceiveBufferSizePredictor 的 previousReceiveBufferSize() 方法不是从 OioDatagramWorker 类调用的(而它是从 NioDatagramWorker 调用的)
所以,我们最初将 FixedReceivedBufferSizePredictor 设置为 (2*1024*1024)
观察到的行为
在不同的机器上运行(不同的处理能力),我们看到 Netty 接收的字节数不同。在我们的例子中,我们通过 UDP 流式传输视频,我们能够使用流式传输字节的回放来诊断读取的字节的质量(发送的数据包大小约为 1000 字节)。
然后我们对不同的缓冲区大小进行了试验,发现 1024*1024 似乎可以让事情变得更好......但真的不知道为什么。
在查看 FixedReceivedBufferSizePredictor 的工作原理时,我们意识到它只是在每次数据包进入时创建一个新缓冲区。在我们的例子中,它会创建一个 2*1024*1024 字节的新缓冲区,无论数据包是 1000字节或 3 MB。我们的数据包只有 1000 字节,所以我们认为这不是我们的问题。这里的任何逻辑都会导致性能问题吗?例如,每次数据包进来时创建缓冲区?
我们的解决方法
然后我们考虑了使缓冲区大小动态化的方法,但意识到我们不能使用上面提到的 AdaptiveReceiveBufferSizePredictor。我们试验并创建了我们自己的 MyAdaptiveReceiveBufferSizePredictor 以及随附的 MyOioDatagramChannelFactory、*Channel、*ChannelFactory、*PipelineSink、*Worker 类(最终调用 MyAdaptiveReceiveBufferSizePredictor)。预测器只是将缓冲区大小更改为基于最后一个数据包大小的缓冲区大小的两倍或减小它。这似乎有所改善。
【问题讨论】: