Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Netty ServerBootStrap选项或childOption及其缓冲区大小对速度的影响_Java_Performance_Netty - Fatal编程技术网

Java Netty ServerBootStrap选项或childOption及其缓冲区大小对速度的影响

Java Netty ServerBootStrap选项或childOption及其缓冲区大小对速度的影响,java,performance,netty,Java,Performance,Netty,当缓冲区大小增加到超过默认值和/或在ServerBootStrap对象中选择了不正确的覆盖位置(option或childOption)时,Netty似乎会降低上载/下载速度。当连接具有更大的延迟(约300ms)时,这种情况变得更加明显 设置: Netty客户端位于MacOS上,仅具有默认值。使用300毫秒DNS延迟的“网络链路调节器”。默认值:SendBuffer/ReceiveBuffer/LowWaterMark/HighWaterMark-128KB/128KB/32KB/64KB Net

当缓冲区大小增加到超过默认值和/或在ServerBootStrap对象中选择了不正确的覆盖位置(
option
childOption
)时,Netty似乎会降低上载/下载速度。当连接具有更大的延迟(约300ms)时,这种情况变得更加明显

设置

Netty客户端位于MacOS上,仅具有默认值。使用300毫秒DNS延迟的“网络链路调节器”。默认值:SendBuffer/ReceiveBuffer/LowWaterMark/HighWaterMark-128KB/128KB/32KB/64KB

Netty服务器位于Windows 8.1上,具有默认值SendBuffer/ReceiveBuffer/LowWaterMark/HighWaterMark-64KB/64KB/32KB/64KB

Netty版本4.1.6最终版

使用具有以下设置的IO图形使用wireshark测量速度:Y轴->总和(Y字段),Y字段->tcp.len

设备位于本地网络上

结果(速度值)

服务器->客户端传输(将SO_SNDBUF和水印低/高值设置为0.5*SO_SNDBUF/SO_SNDBUF):

客户端->服务器传输(设置SO_RCVBUF):

服务器代码:

“args”值:

“sendToClient”/“sendToServer”(隐式)表示传输方向。 覆盖类型的“选项”/“子选项”。 “1”/“2”/“3”表示缓冲区值

ObjectEchoServer.java

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;

public final class ObjectEchoServer {

    static final int PORT = 8007;

    public static void main(String[] args) throws Exception {
        int rcvBuf, sndBuf, lowWaterMark, highWaterMark;
        rcvBuf = sndBuf = lowWaterMark = highWaterMark = 0;
        switch (args[2]){
            case "1":
                rcvBuf = 64;
                sndBuf = 64;
                lowWaterMark = 32;
                highWaterMark = 64;
                break;
            case "2":
                rcvBuf = 128;
                sndBuf = 128;
                lowWaterMark = 64;
                highWaterMark = 128;
                break;
            case "3":
                rcvBuf = 1024;
                sndBuf = 1024;
                lowWaterMark = 512;
                highWaterMark = 1024;
                break;

        }

        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .handler(new LoggingHandler(LogLevel.INFO))
             .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline p = ch.pipeline();
                    p.addLast(
                            new ObjectEncoder(),
                            new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
                            new ObjectEchoServerHandler(args[0]));
                }
             });
            if(args[1].equalsIgnoreCase("childOption")) {
                b.childOption(ChannelOption.SO_RCVBUF, rcvBuf * 1024);
                b.childOption(ChannelOption.SO_SNDBUF, sndBuf * 1024);
                b.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(lowWaterMark * 1024, highWaterMark * 1024));
            } else if(args[1].equalsIgnoreCase("option")){
                b.option(ChannelOption.SO_RCVBUF, rcvBuf * 1024);
                b.option(ChannelOption.SO_SNDBUF, sndBuf * 1024);
                b.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(lowWaterMark * 1024, highWaterMark * 1024));
            }
            // Bind and start to accept incoming connections.
            b.bind(PORT).sync().channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
客户端代码:

“args”值:

“sendToClient”/“sendToServer”(隐式)表示传输方向

ObjectEchoClient.java

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;

public final class ObjectEchoClient {

    static final String HOST = System.getProperty("host", "127.0.0.1");
    static final int PORT = 8007;
    static final int SIZE = 256;

    public static void main(String[] args) throws Exception {

        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline p = ch.pipeline();
                    p.addLast(
                            new ObjectEncoder(),
                            new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
                            new ObjectEchoClientHandler(args[0]));
                    System.out.println("senbuf:"+ ch.config().getSendBufferSize());
                    System.out.println("waterhigh:"+ ch.config().getWriteBufferWaterMark().high());
                    System.out.println("waterlow:"+ ch.config().getWriteBufferWaterMark().low());
                    System.out.println("recbuf:"+ ch.config().getReceiveBufferSize());

                }
             });
            // Start the connection attempt.
            b.connect(HOST, PORT).sync().channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}
导入io.netty.bootstrap.bootstrap;
导入io.netty.channel.*;
导入io.netty.channel.nio.NioEventLoopGroup;
导入io.netty.channel.socket.SocketChannel;
导入io.netty.channel.socket.nio.NioSocketChannel;
导入io.netty.handler.codec.serialization.ClassResolvers;
导入io.netty.handler.codec.serialization.ObjectDecoder;
导入io.netty.handler.codec.serialization.ObjectEncoder;
公共最终类ObjectEchoClient{
静态最终字符串HOST=System.getProperty(“HOST”,“127.0.0.1”);
静态最终int端口=8007;
静态最终整数大小=256;
公共静态void main(字符串[]args)引发异常{
EventLoopGroup=new NioEventLoopGroup();
试一试{
引导b=新引导();
b、 组(组)
.channel(NioSocketChannel.class)
.handler(新的通道初始值设定项(){
@凌驾
public void initChannel(SocketChannel ch)引发异常{
ChannelPipeline p=通道管道();
p、 addLast(
新的ObjectEncoder(),
新的ObjectDecoder(ClassResolver.cacheDisabled(null)),
新对象EchoClientHandler(args[0]);
System.out.println(“senbuf:+ch.config().getSendBufferSize());
System.out.println(“waterhigh:+ch.config().getWriteBufferWaterMark().high());
System.out.println(“滑铁卢:+ch.config().getWriteBufferWaterMark().low());
System.out.println(“recbuf:+ch.config().getReceiveBufferSize());
}
});
//开始连接尝试。
b、 连接(主机,端口).sync().channel().closeFuture().sync();
}最后{
group.ShutdownGracely();
}
}
}
ObjectEchoClientHandler.java

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class ObjectEchoServerHandler extends ChannelInboundHandlerAdapter {
    private Object msg;
    ChannelHandlerContext ctx;
    String sendToClient;

    public ObjectEchoServerHandler(String sendToClient){
        this.sendToClient = sendToClient;

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx){
        this.ctx = ctx;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if(sendToClient.equalsIgnoreCase("sendToClient")) {//send a data stream to server
            this.msg = msg;
            ctx.writeAndFlush(msg).addListener(trafficGenerator);
        } //else receive a data stream from client
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

    private final ChannelFutureListener trafficGenerator = new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future) {
            if (future.isSuccess()) {
                ctx.writeAndFlush(msg).addListener(trafficGenerator);
            } else {
                future.cause().printStackTrace();
                future.channel().close();
            }
        }
    };
}
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.util.ArrayList;
import java.util.List;

public class ObjectEchoClientHandler extends ChannelInboundHandlerAdapter {

    private final List<String> firstMessage;
    private ChannelHandlerContext ctx;
    private String sendToClient;

    ObjectEchoClientHandler(String sendToClient) {
        this.sendToClient = sendToClient;

        firstMessage = new ArrayList<>(ObjectEchoClient.SIZE);
        for (int i = 0; i < ObjectEchoClient.SIZE; i++) {
            firstMessage.add(Integer.toString(i));
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        this.ctx = ctx;
      if(sendToClient.equalsIgnoreCase("sendToClient")) {//get a data stream from server
          this.ctx.writeAndFlush(firstMessage);
      } else {//send a stream of to server
          this.ctx.writeAndFlush(firstMessage).addListener(trafficGenerator);
      }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ctx.flush();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

    private final ChannelFutureListener trafficGenerator = new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future) {
            if (future.isSuccess()) {
                ctx.writeAndFlush(firstMessage).addListener(trafficGenerator);
            } else {
                future.cause().printStackTrace();
                future.channel().close();
            }
        }
    };
}
导入io.netty.channel.ChannelFuture;
导入io.netty.channel.ChannelFutureListener;
导入io.netty.channel.ChannelHandlerContext;
导入io.netty.channel.ChannelInboundHandlerAdapter;
导入java.util.ArrayList;
导入java.util.List;
公共类ObjectEchoClientHandler扩展了ChannelInboundHandlerAdapter{
私人最终名单第一条消息;
专用通道HandlerContext ctx;
私有字符串发送到客户端;
ObjectEchoClientHandler(字符串发送到客户端){
this.sendToClient=sendToClient;
firstMessage=newarraylist(ObjectEchoClient.SIZE);
for(int i=0;i
大问题:

设置缓冲区的正确方式/位置是什么?我发现的信息(大部分是代码示例)到处都是

One thread()表示每个客户端信息都应该使用
ServerBootStrap.childOption
,因此我认为这两个缓冲区都应该在
ServerBootStrap.childOption

中,我认为这是正确的
b.option(ChannelOption.SO_RCVBUF,RCVBUF*1024);
b、 选项(ChannelOption.SO_SNDBUF,SNDBUF*1024)

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;

public final class ObjectEchoClient {

    static final String HOST = System.getProperty("host", "127.0.0.1");
    static final int PORT = 8007;
    static final int SIZE = 256;

    public static void main(String[] args) throws Exception {

        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .handler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline p = ch.pipeline();
                    p.addLast(
                            new ObjectEncoder(),
                            new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
                            new ObjectEchoClientHandler(args[0]));
                    System.out.println("senbuf:"+ ch.config().getSendBufferSize());
                    System.out.println("waterhigh:"+ ch.config().getWriteBufferWaterMark().high());
                    System.out.println("waterlow:"+ ch.config().getWriteBufferWaterMark().low());
                    System.out.println("recbuf:"+ ch.config().getReceiveBufferSize());

                }
             });
            // Start the connection attempt.
            b.connect(HOST, PORT).sync().channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.util.ArrayList;
import java.util.List;

public class ObjectEchoClientHandler extends ChannelInboundHandlerAdapter {

    private final List<String> firstMessage;
    private ChannelHandlerContext ctx;
    private String sendToClient;

    ObjectEchoClientHandler(String sendToClient) {
        this.sendToClient = sendToClient;

        firstMessage = new ArrayList<>(ObjectEchoClient.SIZE);
        for (int i = 0; i < ObjectEchoClient.SIZE; i++) {
            firstMessage.add(Integer.toString(i));
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        this.ctx = ctx;
      if(sendToClient.equalsIgnoreCase("sendToClient")) {//get a data stream from server
          this.ctx.writeAndFlush(firstMessage);
      } else {//send a stream of to server
          this.ctx.writeAndFlush(firstMessage).addListener(trafficGenerator);
      }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ctx.flush();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

    private final ChannelFutureListener trafficGenerator = new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future) {
            if (future.isSuccess()) {
                ctx.writeAndFlush(firstMessage).addListener(trafficGenerator);
            } else {
                future.cause().printStackTrace();
                future.channel().close();
            }
        }
    };
}