如何编写高性能的Netty客户端

16

我需要一个非常高效的TCP客户端来发送Google Protocol Buffer消息。我一直在使用Netty库来开发服务器/客户端。

在测试中,服务器似乎能够处理多达500,000个事务每秒,没有太多问题,但客户端往往会在每秒大约180,000个交易时达到峰值。

我基于Netty文档中提供的示例构建了我的客户端,但不同之处在于我只想发送消息而不需要响应(这是大多数示例所得到的)。有没有办法优化我的客户端,以便我可以实现更高的TPS?

我的客户端是否应该维护多个通道,还是应该通过单个通道实现更高的吞吐量?


2
时间确实听起来像客户端正在等待响应...只是一个想法-既然它听起来像一个相当简单的服务,你是否尝试过使用原始套接字? - Marc Gravell
1
如果有人为这种类型的客户解决了问题,能否请分享客户代码示例以及使用的Netty版本?目前我被版本更改困扰着。 - Jubin Patel
2个回答

17

1)如果客户端只对发送感兴趣,不对接收感兴趣,您可以像下面这样禁用从通道读取:

如果客户端只需向服务器发送数据,而不需要从服务器接收数据,则可以通过以下方式禁用从通道读取:


channel.disable(OP_READ);
channel.setReadable(false);

2) 通过为每个客户端添加多个客户端通道,可以很容易地提高吞吐量,并且还可以扩展。

3) 并且您可以进行以下调整以改善总体性能(用于读取/写入)

  • 最好使用类似SEDA的管道,通过添加具有OrderdMemoryAwareThreadPoolExecutor的ExecutionHandler来实现,(具有最佳值的最小,最大通道内存)

bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
    @Override
    public ChannelPipeline getPipeline() throws Exception {
        return Channels.pipeline(
                executionHandler1,//sharable
                new MessageDecoderHandler(),
                new MessageEncoderHandler(),
                executionHandler2,//sharable
                new BusinessLogicHandler1(),
                new BusinessLogicHandler2());
    }
});
  • 将通道的writeBufferHighWaterMark设置为最佳值(确保设置大值不会创建拥塞)

    bootstrap.setOption("writeBufferHighWaterMark", 10 * 64 * 1024);

  • 设置SO_READ和SO_WRITE缓冲区大小

    bootstrap.setOption("sendBufferSize", 1048576); bootstrap.setOption("receiveBufferSize", 1048576);

  • 启用TCP No delay

    bootstrap.setOption("tcpNoDelay", true);


  • 谢谢,关于第二点有一个问题。最好的方法是什么?我应该创建多个通道,并将它们的处理程序放在某种工作队列中以处理请求吗? - Dave
    @Dave 看看这个答案,了解客户端如何使用多个连接:https://dev59.com/xGsz5IYBdhLWcg3wcXXF#7905761 - Abe
    我发现 setReadable(false) 可能不是一个好主意,除非你有一种方法知道远程端口断开连接而不尝试读取通道。当远程端口挂断时,read() 返回 -1 - Chetan Narsude

    4

    我不确定"tcpNoDelay"是否有助于提高吞吐量。延迟是为了提高性能的。无论如何,我尝试了一下,发现吞吐量实际上下降了90%以上。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接