Java Netty负载测试问题

我使用文本协议编写了​​接受连接并轰击消息(〜100字节)的服务器,并且我的实现能够使用3rt方客户端发送有关环回400K /秒的消息。 我选择了Netty来完成这项任务,SUSE 11 RealTime,JRockit RTS。 但是当我开始基于Netty开发自己的客户端时,我遇到了巨大的吞吐量(从400K降到1.3K msg / sec)。 客户端的代码非常简单。 请你给我一个建议或者举例说明如何写更有效的客户。 实际上,我更关心延迟,但是从吞吐量测试开始,我认为环回时1.5Kmsg / sec是不正常的。 PS客户端的目的是只接收来自服务器的消息,并且很少发送心跳。

Client.java

public class Client {

private static ClientBootstrap bootstrap;
private static Channel connector;
public static boolean start()
{
    ChannelFactory factory =
        new NioClientSocketChannelFactory(
                Executors.newCachedThreadPool(),
                Executors.newCachedThreadPool());
    ExecutionHandler executionHandler = new ExecutionHandler( new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576));

    bootstrap = new ClientBootstrap(factory);

    bootstrap.setPipelineFactory( new ClientPipelineFactory() );

    bootstrap.setOption("tcpNoDelay", true);
    bootstrap.setOption("keepAlive", true);
    bootstrap.setOption("receiveBufferSize", 1048576);
    ChannelFuture future = bootstrap
            .connect(new InetSocketAddress("localhost", 9013));
    if (!future.awaitUninterruptibly().isSuccess()) {
        System.out.println("--- CLIENT - Failed to connect to server at " +
                           "localhost:9013.");
        bootstrap.releaseExternalResources();
        return false;
    }

    connector = future.getChannel();

    return connector.isConnected();
}
public static void main( String[] args )
{
    boolean started = start();
    if ( started )
        System.out.println( "Client connected to the server" );
}

}

ClientPipelineFactory.java

public class ClientPipelineFactory  implements ChannelPipelineFactory{

private final ExecutionHandler executionHandler;
public ClientPipelineFactory( ExecutionHandler executionHandle )
{
    this.executionHandler = executionHandle;
}
@Override
public ChannelPipeline getPipeline() throws Exception {
    ChannelPipeline pipeline = pipeline();
    pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
              1024, Delimiters.lineDelimiter()));
    pipeline.addLast( "executor", executionHandler);
    pipeline.addLast("handler", new MessageHandler() );

    return pipeline;
}

}

MessageHandler.java
public class MessageHandler extends SimpleChannelHandler{

long max_msg = 10000;
long cur_msg = 0;
long startTime = System.nanoTime();
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
    cur_msg++;

    if ( cur_msg == max_msg )
    {
        System.out.println( "Throughput (msg/sec) : " + max_msg* NANOS_IN_SEC/(     System.nanoTime() - startTime )   );
        cur_msg = 0;
        startTime = System.nanoTime();
    }
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
    e.getCause().printStackTrace();
    e.getChannel().close();
}

}

更新。 在服务器端有一个周期性线程写入接受的客户端通道。 通道很快就变得不可写了。 更新N2。 在流水线中添加了OrderedMemoryAwareExecutor,但仍然存在非常低的吞吐量(大约4k msg / sec)

固定。 我把执行器放在整个管道堆的前面,它解决了!


如果服务器发送固定大小(〜100字节)的消息,则可以将ReceiveBufferSizePredictor设置为客户机引导程序,这将优化读取

bootstrap.setOption("receiveBufferSizePredictorFactory",
            new AdaptiveReceiveBufferSizePredictorFactory(MIN_PACKET_SIZE, INITIAL_PACKET_SIZE, MAX_PACKET_SIZE));

根据您发布的代码段:客户端的nio工作线程正在做所有的事情,所以它将忙于解码和执行消息处理程序。 你必须添加一个执行处理程序。

您曾经说过,通道从服务器端变得不可写入,因此您可能需要调整服务器引导程序中的水印大小。 您可以定期监视写入缓冲区大小(写入队列大小),并确保该通道变得不可写入,因为消息无法写入网络。 它可以通过像下面这样的util类来完成。

package org.jboss.netty.channel.socket.nio;

import org.jboss.netty.channel.Channel;

public final class NioChannelUtil {
  public static long getWriteTaskQueueCount(Channel channel) {
    NioSocketChannel nioChannel = (NioSocketChannel) channel;
    return nioChannel.writeBufferSize.get();
  }
}
链接地址: http://www.djcxy.com/p/95211.html

上一篇: Java Netty load testing issues

下一篇: latency in netty due to passing requests from boss thread to worker thread?