3

私は、テキストプロトコルを使用して接続を受け入れ、メッセージ(〜100バイト)を攻撃するサーバーを作成しました。私の実装では、サードパーティクライアントとのループバック400K/秒メッセージを送信できます。このタスクにはNetty、SUSE 11 RealTime、JRockitRTSを選びました。しかし、Nettyに基づいて独自のクライアントを開発し始めたとき、スループットが大幅に低下しました(400Kから1.3K msg /秒に減少)。クライアントのコードは非常に単純です。より効果的なクライアントを作成する方法について、アドバイスや例を示していただけませんか。実際、私はレイテンシーにもっと関心がありますが、スループットテストから始めており、ループバックで1.5Kmsg/秒になるのは正常ではないと思います。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)

修理済み。パイプラインスタック全体の前にエグゼキュータを配置しましたが、うまくいきました。

4

1 に答える 1

3

サーバーが固定サイズ(〜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();
  }
}
于 2012-01-28T17:27:51.403 に答える