【问题标题】:latency in netty due to passing requests from boss thread to worker thread?由于将请求从老板线程传递到工作线程而导致网络延迟?
【发布时间】:2012-01-29 04:04:30
【问题描述】:

我对 Netty(服务器端)、TCP/IP 应用程序有一些疑问;

我想知道在将请求从老板线程传递到工作线程时是否会因为 netty(由于缺少配置等)而存在延迟?

我正在使用:

new OrderedMemoryAwareThreadPoolExecutor(350, 0, 0, 1, TimeUnit.SECONDS);

实际上,我设置了最大线程数350,因为我不确定最佳数量。我每分钟记录一次同时工作的线程数,似乎平均值太低(勉强超过10)。所以我会减少这个数字,因为它不是必需的。

是否有任何其他参数,我应该注意以获得最佳性能的重要点?

bootstrap.setOption("tcpNoDelay", true); - 设置这个参数有什么缺点吗?考虑到交货时间非常重要。

线程池执行器:

OrderedMemoryAwareThreadPoolExecutor executor = new OrderedMemoryAwareThreadPoolExecutor(48, 0, 0, 1, TimeUnit.SECONDS);

这是我的管道工厂:

    ChannelPipeline pipeline = pipeline();
    pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(GProperties.getIntProperty("decoder.maxFrameLength", 8000 * 1024), Delimiters.nulDelimiter()));
    pipeline.addLast("stringDecoder", new StringDecoder( CharsetUtil.UTF_8 ));      
    pipeline.addLast("frameEncoder", new NullTermMessageEncoder());
    pipeline.addLast("stringEncoder", new JSONEncoder( CharsetUtil.UTF_8 ));
        pipeline.addLast("timeout", new IdleStateHandler(idleTimer, 42 , 0, 0));
    pipeline.addLast("executor", new ExecutionHandler(executor));
    pipeline.addLast("handler", new GServerHandler());

和 ServerBootstrap:

gServerBootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
        gServerBootstrap.setPipelineFactory(new GServerPipelineFactory());
                gServerBootstrap.setOption("backlog", 8129);
                gServerBootstrap.setOption("child.tcpNoDelay", true);
        gServerBootstrap.bind(new InetSocketAddress(GProperties.getIntProperty("server.port", 7679)));

您对此配置有何建议?

【问题讨论】:

    标签: java performance tcp netty tcplistener


    【解决方案1】:

    Netty Boss 线程仅用于建立连接,工作线程用于运行 NioWorker(非阻塞读/写)或 OioWorker(阻塞读/写)。

    如果你有一个执行处理器,工作线程会将消息事件提交给 OrderedMemoryAwareThreadPoolExecutor。

    1) 将 Netty I/O 工作线程数增加到超过处理器数 * 2 将无济于事。如果您使用分阶段执行器,为非 I/O 任务设置多个分阶段执行处理程序可能会增加延迟。

    注意:最好在 OMTPE 中设置自己的 ObjectSizeEstimator 实现 构造函数,因为许多 CPU 周期都用于计算已使用的通道内存。

    2) 还有一些其他的Netty参数你可以试试

       //setting buffer size can improve I/O
       bootstrap.setOption("child.sendBufferSize", 1048576);
       bootstrap.setOption("child.receiveBufferSize", 1048576); 
    
       // better to have an receive buffer predictor 
       bootstrap.setOption("receiveBufferSizePredictorFactory", new AdaptiveReceiveBufferSizePredictorFactory(MIN_PACKET_SIZE, INITIAL_PACKET_SIZE, MAX_PACKET_SIZE))  
    
       //if the server is sending 1000 messages per sec, optimum write buffer water marks will
       //prevent unnecessary throttling, Check NioSocketChannelConfig doc   
       bootstrap.setOption("writeBufferLowWaterMark", 32 * 1024);
       bootstrap.setOption("writeBufferHighWaterMark", 64 * 1024);
    

    3) 服务器引导应该是 bootstrap.setOption("child.tcpNoDelay", true)。

    有一个实验性的隐藏参数:

    Netty NioWorker 正在使用 SelectorUtil.select 等待选择器事件,等待时间是硬编码在 SelectorUtil 中的,

    selector.select(500);
    

    设置一个较小的值可以在 netty sctp 传输实现中提供更好的性能。不确定 TCP。

    【讨论】:

    • 我必须在操作系统级别(服务器)为 tcpNoDelay 做些什么吗?更改配置,设置全局环境变量等?服务器是 Centos。
    • linux下可以使用sysctl命令调tcp栈参数,但是tcp no delay是socket级别的参数,所以必须使用bootstrap.setOption
    • 调整 TCP 堆栈将非常具体地满足您的性能要求,并且那里有很多文章。这些是我在我的 2.6 Kernel gist.github.com/1554191 中可以看到的参数
    • 缓冲区大小和 WaterMarks 如何影响网络性能?
    • 1) 为套接字缓冲区设置最佳大小可减少读/写调用次数 2) 设置写水印大小可防止不必要的限制(进入只读模式)
    【解决方案2】:

    Q1) 一切都会增加延迟。 Netty 非常高效,所以如果延迟对于 95% 以上的用例来说太高,我会感到惊讶

    Q2)在您开始担心之前测试您自己的性能并确定它是否存在问题(延迟或吞吐量)。

    Q3) 此选项可能会有所帮助。它不应该使情况变得更糟。许多现代操作系统的自我调整都非常好,我发现它不像以前那样有很大的不同。

    您能否说明您想要达到的延迟时间,因为它会对您的设计产生重大影响?是 10 ms、1 ms、100 us、10 us?

    【讨论】:

    • 彼得,我知道这听起来很疯狂,但它可以超过 1000 毫秒吗?关于您对第二季度延迟的回答非常重要,因为此应用程序是游戏服务器。但是捕捉实际问题太难了,因为可能是由于客户端互联网连接速度慢,客户端电脑不佳等多种原因。
    • 根据您的操作,延迟可能会超过 1000 毫秒。但是,可以在 Java 中设计延迟小于 100 微秒的系统(对于您控制的部分)
    • 除非没有可用线程,否则将工作单元从 netty IO 线程移交给工作线程的延迟是不可能的 1000 毫秒。根据我的经验(我正在运行拥有数百万用户的数百台服务器)大约需要 1-2 毫秒。
    • 我怀疑 OP 需要更好地了解他的延迟来自何处。我建议他为事件生命周期中的所有阶段加上时间戳,例如接收、处理和响应请求。您可以在 300 毫秒(往返)内 ping 世界另一端的服务器
    【解决方案3】:

    1) 我想知道在将请求从老板线程传递到工作线程时是否会因为 netty(由于缺少配置等)而存在延迟?

    我认为这里没有太多延迟。线程在一个池中,只需要给它们工作。

    问题 2) 是否有任何其他参数,我应该注意以获得最佳性能的重要点?

    谈到“最佳”性能时,我进行了一系列测试,最终使用的线程数大约是机器上物理处理器数量的 16*。我尝试了多达数千个线程数,但是当它们真正受到猛烈抨击时,它们最终在 GC 中颠簸。

    问题 3) bootstrap.setOption("tcpNoDelay", true);.设置此参数有什么缺点吗?考虑到交货时间非常重要。

    一定要设置这个。

    【讨论】:

    • 我会尝试设置 tcpNoDelay 参数。既然是游戏服务器更新就得等晚上了=)顺便问一下为什么是16??
    • 如果我做对了请纠正我 -> 16 x(处理器数量)
    • 这最终成为线程、吞吐量和内存使用的最佳权衡。
    • 是的。但就像我说的 - 我测试了各种不同的东西。
    • Kylar,Netty 的日志消息值得看吗?
    猜你喜欢
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    • 2018-01-01
    • 2013-11-02
    • 1970-01-01
    • 2011-01-28
    • 2018-01-30
    • 1970-01-01
    相关资源
    最近更新 更多