Netty可以作为客户有效地处理大量传出连接吗?

时间:2012-04-03 21:53:43

标签: client nio netty

我正在创建一个客户端 - 服务器关系,通过持久的TCP连接,单个客户端将连接到任意数量的服务器。实际的服务器数量尚未确定,但设计目标是拍摄1000个。

我找到了一个使用直接Java NIO的例子,它几乎完全符合我的心理模型,它可以如何工作:

http://drdobbs.com/jvm/184406242

通常,它会打开所有通道并将它们添加到监视java.nio.channels.Selector的单个线程中。特别是,使用Selector可以比使用每个通道的标准线程更好地扩展。

我宁愿使用像Netty这样的(稍微)更高级别的套接字框架,而不是直接使用Java NIO。不幸的是,我无法确定Netty如何处理这样的案件。也就是说,我发现的示例和讨论都倾向于以服务器端为中心,接受大量并发连接。

但是从客户端那样做呢?如果我创建大量频道并等待他们的活动,Netty将如何在后端处理这个?

3 个答案:

答案 0 :(得分:3)

这不是您问题的直接答案,但我希望它仍然有用。下面,我将介绍一种确定您正在寻找答案的方法。这是我最近为即将开展的项目做的事情。

与OIO(旧IO)相比,Netty框架和NIO的异步性质确实为您的应用程序提供了更好的内存和CPU使用特性。在Netty中处理缓冲区的方式也是有益的,因为它可以帮助您避免复制字节缓冲区。关键是将为您处理所有线程池和NIO详细信息,使您可以专注于业务逻辑。你提到了NIO选择器,你将从中受益;关于Netty的好处是你可以获得好处,而不必担心自己的实现,因为它已经为你完成了。

我对客户端的理解是它与服务器端非常相似,应该为您提供相应的性能提升(只要您的业务逻辑不会引入任何性能问题)。

我的建议是把一个或多或少做你想要的原型放在一起。省去任何耗时的细节,只需添加你需要的基本Netty处理程序来制作有用的东西。

然后我会使用jmeter来调用您的客户端以将负载应用于服务器和客户端。使用jconsolejvisualvm之类的内容将向您显示负载下客户端和服务器的性能特征。您也可以尝试jprobe。您可以在jmeter中添加一个指示吞吐量的侦听器。我建议在服务器模式下使用jmeter,在另一台机器上使用客户端,在另一台机器上使用服务器。这是一些前期工作,但如果您决定继续前进,您将准备好这些工具,以便继续进行进一步测试。

我怀疑一个体面的Netty实现没有引入任何无关的性能不佳的组件会给你你正在寻找的性能特征,但是,唯一可以确定的方法是在预期的负载下测量系统。

您需要在此类负载下定义预期负载的外观和所需的性能特征。根据这些输入,您可以测量您的系统,以确定它是否符合您的期望。我个人认为没有人可以告诉你它是否会按照理想的方式运作。你必须衡量它。这是了解系统是否能满足您需求的唯一可靠方法。

  

我宁愿使用像Netty这样的(稍微)更高级别的套接字框架,而不是直接使用Java NIO。

这是正确的方法。您可以尝试实现自己的NIO服务器和客户端,但是为什么在您已经获得高度精炼的框架的好处时呢?

答案 1 :(得分:2)

Netty将使用最多x个工作线程来处理您的工作。每个工作线程都有一个选择器,用于向其注册通道。使用的工作线程数是可配置的,默认为2 * cpu-count。

答案 2 :(得分:1)

正如您在Netty的doc [http://netty.io/docs/stable/guide/html/#start.9][1]中的示例中所看到的,您可以准确控制工作线程的数量(意味着客户端的底层选择器数量。 Netty以一种简单的方式解决了许多难以处理的问题,例如NIO vs SSL,并且有许多用于Zip的默认编码器/解码器......等等。 几个星期前我开始使用Netty,它很快就进入了。 (我建议使用里面的所有示例代码下载项目,其中有很多文档在上面的url中找不到。

            ChannelFactory factory = new NioClientSocketChannelFactory(
                      Executors.newCachedThreadPool(),
                      Executors.newCachedThreadPool());

            ClientBootstrap bootstrap = new ClientBootstrap(factory);

            bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
             public ChannelPipeline getPipeline() {
                    return Channels.pipeline(new TimeClientHandler());
             }
            });

            bootstrap.setOption("tcpNoDelay", true);
            bootstrap.setOption("keepAlive", true);

            bootstrap.connect(new InetSocketAddress(host, port));
祝你好运,

雷诺