标签:throughput low-latency performance netty java
我编写了使用文本协议接受连接并轰炸消息(〜100字节)的服务器,并且我的实现能够与3rt方客户端发送回送400K / sec消息.我为此任务选择了Netty,即SUSE 11 RealTime,JRockit RTS.
但是,当我开始基于Netty开发自己的客户端时,吞吐量却急剧下降(从400K msg / sec降低到1.3K msg / sec).客户端的代码非常简单.能否请您提供建议或显示示例,说明如何编写更有效的客户.实际上,我实际上更关心延迟,但是从吞吐量测试开始,我认为在环回中以1.5Kmsg / sec的速度正常是不正常的.
附言客户端的目的只是从服务器接收消息,很少发送心跳信号.
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 worker线程正在做管道中的所有事情,因此它将忙于解码和执行消息处理程序.您必须添加一个执行处理程序.
您已经说过,通道已无法从服务器端写入,因此您可能必须在服务器引导程序中调整水印大小.您可以定期监视写缓冲区大小(写队列大小),并确保由于消息无法写到网络而使通道变得不可写.可以通过以下类似的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();
}
}
标签:throughput,low-latency,performance,netty,java
来源: https://codeday.me/bug/20191201/2083736.html
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。