Java 向大量客户端实时分发小消息的Netty选项?

Java 向大量客户端实时分发小消息的Netty选项?,java,real-time,netty,out-of-memory,Java,Real Time,Netty,Out Of Memory,我正在设计一个(近乎)实时的Netty服务器,通过internet将大量非常小的消息分发给大量客户端。在内部测试中,尽可能快地进行测试,我发现我可以毫不费力地处理10k客户端,但现在我们正试图跨越互联网,在互联网上,延迟、带宽等变化非常大,我们遇到了可怕的outOfMemory问题,即使有2 Gig的RAM 我尝试过各种解决方法(将套接字堆栈的大小设置得更小,设置高水位线和低水位线,取消太旧的东西),它们有一点帮助,但似乎只起了一点作用。有什么好方法可以优化Netty,以便在不造成重大延迟的情况

我正在设计一个(近乎)实时的Netty服务器,通过internet将大量非常小的消息分发给大量客户端。在内部测试中,尽可能快地进行测试,我发现我可以毫不费力地处理10k客户端,但现在我们正试图跨越互联网,在互联网上,延迟、带宽等变化非常大,我们遇到了可怕的outOfMemory问题,即使有2 Gig的RAM

我尝试过各种解决方法(将套接字堆栈的大小设置得更小,设置高水位线和低水位线,取消太旧的东西),它们有一点帮助,但似乎只起了一点作用。有什么好方法可以优化Netty,以便在不造成重大延迟的情况下发送大量小消息?而且,大部分信息只包含一种信息,我并不特别关心它是否到达。我会使用UDP,但因为我们不控制客户端,所以不太可能。是否可以仅为此类消息设置单独的超时,而不影响其他消息


非常感谢您提供的任何见解。

通常,如果看到outOfMemory,您可以使用线程转储工具转储线程。或者使用类似jvirtualvm和jconsole的东西来找出哪个类没有得到GCed,并继续消耗您的内存。 2G对于现在的64位机器来说已经不算大了。试着把这个数字调大到3或4G左右,看看你是否达到了OOM。
如果您发现您可以在LAN中轻松处理10k连接,请尝试在netty处理程序中添加一点延迟。检查发生了什么。

您可能需要查看该方法。它用于使用硬件和软件在分布式系统中分配工作负载。适合您的系统的细节取决于几个因素,包括硬件升级等。当然,2GB的RAM对于服务器10k用户来说是相当小的,您需要增加这个限制。

您没有说订阅流是恒定的还是突发的。您也没有说明客户端每秒是否必须支持最少数量的消息

考虑到我对Redis一无所知,以下哪一项是可行的

  • 对于您不关心的消息,如果channel.iswriteable()==false,则立即放弃。不幸的是,我不知道如何取消Netty发送缓冲区中的消息。无论如何,您都无法取消已传递到TCP发送缓冲区的消息,因此这并不是真正可以依赖的
  • 从订阅到最慢客户端的接收速度较慢
  • 确定哪些客户端无法跟上(可能使用写入超时处理程序),并将它们移动到可以减慢速度的单独订阅。将已发布的邮件复制到两个订阅
  • 您可以将要发送到客户端的消息拆分为不同的订阅。如果客户无法跟上,请取消订阅不重要的消息

如果您的平均发送速率随时间的推移高于客户端所能支持的速率,那么除了协商要求的更改以降低最大允许吞吐量之外,没有其他解决方案。

我们使用负载平衡(服务器处理传入消息,通过Redis发布/订阅在服务器之间分发,然后每台服务器将其分发给与其连接的用户),但我们仍然遇到问题,特别是客户端速度慢…我明白了。从你的帖子中看不清楚。我对你只用2GB的RAM就能满足如此高的要求印象深刻。我做到了,这并不是很有启发性,毫不奇怪,大部分内存都被Netty缓冲区和Channel Future Objects占用了。你在下面检查了gc时间压力?您可以在处理程序中添加一个通道组,并检查有/没有连接延迟的情况下有多少并发通道。对不起,我的意思是Redis在服务器之间共享,后端没有问题,只有前端对TCP客户端来说是净的。我如何使用写入超时来降低发送速度以降低cli速度ents?抱歉,我没有说清楚。我建议,如果可以计算平均速度,以及将消息写入网络所需的最长时间,您可以使用WriteTimeoutHandler确定客户端是否落后,并采取某种避免措施,例如订阅较慢的订阅或dro给客户打电话。