我有一台Netty 3.95客户端和服务器。客户端将任务计划发送到服务器。可以发送的计划数量基本上没有限制,有些计划比其他计划更重要。我有三个优先级(高,中,低),我为每个任务计划分配一个优先级(DSCP值,因为我将数据读入客户端。)我希望这允许更重要的任务计划首先到达服务器。 / p>
我已经将路由器的出站数据速率调低到最低限度,我已经将路由器充斥了大约1000个计划。我可以看到任务计划到达服务器并且它们到达的速度非常慢。这告诉我,我已经有效地锁定了路由器的出站数据速率。
在我为每个任务计划执行channel.write之前,我获得了频道的配置并设置了流量等级。
private void setTrafficClass(int code) {
comLink = connection.getChannel();
cfg = (NioSocketChannelConfig) comLink.getConfig();
cfg.setTrafficClass(code);
}
然后我用
跟着这个comLink.write();
任务计划总是按我发送给他们的顺序到达。几乎看起来DSCP代码被忽略了。路由器中启用了DSCP。我使用Wireshark来检查客户端和服务器之间的流量,我注意到并非所有的DSCP代码都是正确的。看起来似乎一组任务计划是立即编写的,无论最后一个DSCP代码是什么,都成为该组的代码。然而,有些是不正确的。
问题
我已经解决了这个问题或更好,但同事看了我的代码,我们发现了问题。我的代码中有一个竞争条件,它不允许设置正确的DSCP代码。如果你查看我的setTrafficClass方法,你可以看到我传入了我想要设置的代码,但重要的是要意识到这个代码是设置连接而不是实际的数据包DSCP。由于我实际上尽可能快地发送了100个任务计划,因此代码不断改变连接的流量类别。如果有足够的时间,它就无法跟上,因此我会看到它的行为。
由于Netty API,解决方案非常简单。在我的情况下,我只使用2个DSCP代码,所以我声明了两个连接。一个连接将处理DSCP代码0分组,另一个连接将处理DSCP代码46分组。一旦我将此代码付诸实践,我就能看到两个DSCP代码都按预期到达发件人。
答案 0 :(得分:0)
我认为,我并没有为所有人做出回答。
在Netty 3.9中,您可以等待channel.write()
返回的未来,或者更好地开始对您自己的ChannelFutureListener进行下一次写作:
channel.write().addListener(yourChannelFutureListener);
您不应该阻止IO Worker线程,因此使用侦听器的原因。但是,如果它太复杂,您可以在管道中添加OrderedMemoryAwareThreadPoolExecutor
,就在应用程序处理程序之前,这样它就会在IO工作线程之外执行,然后使用await()。
在Netty> = 4中,您将拥有一个更简单的writeAndFLush()
方法。
另请注意,IPV4中的值是有限的(请参阅Javadoc)。
但是,我不是这方面的专家,但我认为顺序保留在任何代码中,因为从TCP的角度来看,这是我所知道的强制性。我相信在UDP中它可以按你的需要工作(因为订购时没有确保)。
答案 1 :(得分:0)
就个人而言,我会在代码中执行优先级排序,而不是依靠网络来执行此操作。这样,您就可以将自己与数据可能必须遍历的任何特殊网络配置隔离开来。
有几种方法可以实现这一点,所以以下只是一个例子。
Java至少从Java 6开始提供PriorityQueue实现。它甚至提供了如何使用序列号在不同优先级内维护优先级的示例。如果您的网络速度很慢,您可能希望限制队列中未完成计划的数量。
您可能还需要考虑饥饿是否存在问题 - 即是否产生了许多低优先级计划永远不会被发送的高优先级计划。