分析网络性能

时间:2013-01-30 20:56:54

标签: java linux netty

我正在写一个Netty应用程序。该应用程序在64位八核linux盒上运行

Netty应用程序是一个简单的路由器,它接受请求(传入管道)从请求中读取一些元数据并将数据转发到远程服务(传出管道)。

此远程服务将返回对传出管道的一个或多个响应。 Netty应用程序将响应路由回原始客户端(传入管道)

将有数以千计的客户。将有数以千计的远程服务。

我正在进行一些小规模的测试(10个客户端,10个远程服务),我没有看到10毫秒的低于10.9毫秒的性能,我预计为99.9%。我正在测量客户端和服务器端的延迟。

我正在使用与SPDY类似的完全异步协议。当我们处理FrameDecoder中的第一个字节时,我捕获时间(我只使用System.nanoTime())。我在调用channel.write()之前就停止了计时器。我正在测量从输入管道到输出管道的亚毫秒时间(99.9百分位数),反之亦然。

我还测量了从FrameDecoder中的第一个字节到(上面)message.write()上调用ChannelFutureListener回调的时间。时间是高达数十毫秒(99.9百分位数),但我无法说服自己这是有用的数据。

我最初的想法是我们有一些缓慢的客户。我看了channel.isWritable()并在返回false时记录。在正常情况下,此方法不会返回false

一些事实:

  • 我们正在使用NIO工厂。我们没有定制工人规模
  • 我们已禁用Nagel(tcpNoDelay = true)
  • 我们已启用keep alive(keepAlive = true)
  • CPU空闲时间为90 +%
  • 网络闲置
  • GC(CMS)每100秒左右调用一次非常短的时间

我是否有可以遵循的调试技术来确定我的Netty应用程序运行速度不如我认为的那么快?

感觉channel.write()将消息添加到队列中,而我们(使用Netty的应用程序开发人员)对此队列没有透明性。我不知道队列是Netty队列,OS队列,网卡队列还是什么。无论如何,我正在审查现有应用程序的示例,我没有看到任何反模式我正在关注

感谢您提供任何帮助/见解

3 个答案:

答案 0 :(得分:2)

Netty默认创建Runtime.getRuntime()。availableProcessors()* 2个worker。在你的情况下16。这意味着您可以同时处理多达16个通道,其他通道将等到您释放ChannelUpstreamHandler.handleUpstream / SimpleChannelHandler.messageReceived处理程序,因此不要在这些(IO)线程中执行繁重的操作,否则您可能会卡住其他通道。

答案 1 :(得分:0)

您尚未指定Netty版本,但它听起来像Netty 3。 Netty 4现在稳定,我建议您尽快更新。 您已指定您需要超低延迟时间,以及数万个客户端和服务。这并不是很好。与OIO相比,NIO本身具有潜在的合理潜力。然而,这里的缺陷是OIO可能无法达到您希望的客户数量。尽管如此,我还是会使用OIO事件循环/工厂,看看它是怎么回事。

我自己有一台TCP服务器,在localhost上花费大约30ms来发送和接收并处理一些TCP数据包(从客户端打开套接字直到服务器关闭它开始计算)。如果您确实需要如此低的延迟,我建议您切换远离TCP,因为打开连接需要SYN / ACK垃圾邮件,这将占用您10ms的大部分时间。

答案 2 :(得分:0)

如果您使用System.nanoTime()之类的简单内容,则在多线程环境中测量时间非常困难。想象一下1核心系统:

  1. 线程A被唤醒并开始处理传入的请求。
  2. 线程B被唤醒并开始处理传入的请求。但是,由于我们正在研究1核心机器,这最终要求线程A暂停。
  3. 线程B完成并且执行得非常快。
  4. 线程A恢复并完成,但是花费的时间是线程B的两倍。因为你实际测量了线程A +线程B完成所花费的时间。
  5. 在这种情况下,如何正确测量有两种方法:

    1. 您可以强制执行任何时候只使用一个线程 这允许您测量操作的确切性能,如果操作系统不干扰,则因为在上面的示例中,线程B也可以在您的程序之外。在这种情况下,一种常见的方法是中断干扰,这将为您提供代码速度的估计。然而,您可以假设,在其他空闲的多核上系统,将有另一个核心来处理后台任务,因此您的测量通常不会被中断。将此线程设置为高优先级也有帮助。

    2. 您使用更复杂的工具插入JVM,以实际测量原子执行时间和时间,这将有效地消除外部干扰。一个工具是VisualVM,它已经集成在NetBeans中,可以作为Eclipse的插件使用。

    3. 作为一般建议:使用多于线程的线程并不是一个好主意,除非您知道这些线程会被某些操作频繁地阻塞。当使用非阻塞NIO进行IO操作时,情况并非如此,因为没有阻塞。

      因此,在您的特殊情况下,您实际上会降低客户端的性能,如上所述,因为在高负载下通信将被保留50%的时间。在最坏的情况下,这可能导致客户端甚至遇到超时,因为无法保证线程何时实际恢复(除非您明确请求公平调度)。

相关问题