2

我正在创建一个客户端-服务器关系,其中一个客户端将使用持久 TCP 连接连接到任意数量的服务器。服务器的实际数量尚未确定,但设计目标是争取 1000 台。

我找到了一个使用直接 Java NIO 的示例,该示例几乎完全符合我的心智模型,即它是如何工作的:

http://drdobbs.com/jvm/184406242

通常,它会打开所有通道并将它们添加到监控 java.nio.channels.Selector 的单个线程中。尤其是选择器的使用,使得它比使用标准的每通道线程更好地扩展。

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

但是从客户端这样做呢?如果我创建大量频道并等待它们的事件,Netty 将如何在后端处理这个问题?

4

3 回答 3

4

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

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

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

我的建议是拼凑一个或多或少可以满足您需求的原型。省去任何耗时的细节,只需添加基本的 Netty 处理程序,你需要做一些工作。

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

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

您需要定义预期负载的外观以及在这种负载下所需的性能特征。鉴于这些输入,您可以测量您的系统以确定它是否符合您的期望。我个人认为没有人可以告诉您它是否会以所需的方式运行。你必须测量它。这是了解系统是否能满足您的需求的唯一可靠方法。

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

这是正确的做法。您可以尝试实现自己的 NIO 服务器和客户端,但是当您已经拥有触手可及的高度精炼框架的好处时,为什么还要这样做呢?

于 2012-04-04T04:24:58.150 回答
2

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

于 2012-04-04T06:10:17.927 回答
1

正如您在 Netty 文档 [http://netty.io/docs/stable/guide/html/#start.9][1] 的示例中看到的,您可以准确控制工作线程的数量(意味着底层的数量)选择器)在客户端。Netty 解决了许多很难以简单的方式处理的问题,例如 NIO 与 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));

祝你好运,

雷诺

于 2012-04-04T12:13:14.433 回答