Java 为什么netty上的文件传输非常慢(4.1.5-Final)

Java 为什么netty上的文件传输非常慢(4.1.5-Final),java,performance,file,sockets,netty,Java,Performance,File,Sockets,Netty,在我使用Netty 4.1.5-Final的基于套接字的服务器实现中,当我将视频/图像文件传输成块(20K块大小)时,我发现两个块之间的差异约为350毫秒,不确定如何减小 以下是我的主要服务器代码: 公共类MultimediaServer扩展线程实现IMMultiMediaServer,BeanFactoryAware{ /** *记录器实例 */ 受保护的记录器=Logger.getLogger(this.getClass()); @自动连线 私人财产道具; 私有请求处理程序请求处理程序; 私

在我使用Netty 4.1.5-Final的基于套接字的服务器实现中,当我将视频/图像文件传输成块(20K块大小)时,我发现两个块之间的差异约为350毫秒,不确定如何减小

以下是我的主要服务器代码:

公共类MultimediaServer扩展线程实现IMMultiMediaServer,BeanFactoryAware{
/**
*记录器实例
*/
受保护的记录器=Logger.getLogger(this.getClass());
@自动连线
私人财产道具;
私有请求处理程序请求处理程序;
私人豆厂豆厂;
专用int端口;
专用int maxConnection;
私有int超时=30000;
private EventLoopGroup bossGroup=null;
private EventLoopGroup workerGroup=null;
@凌驾
公开募捐{
试一试{
bossGroup=new NioEventLoopGroup();
workerGroup=new NioEventLoopGroup();
试一试{
ServerBootstrap ServerBootstrap=newserverbootstrap();
serverBootstrap.group(bossGroup,workerGroup.channel)(NioServerSocketChannel.class)
.childHandler(新的通道初始值设定项(){
@凌驾
public void initChannel(SocketChannel ch)引发异常{
ch.pipeline().addLast(“frameDecoder”,新的LengthFieldBasedFrameDecoder(Integer.MAX_值,0,Const.PACKET_标头_长度,0,Const.PACKET_标头_长度));
ch.pipeline().addLast(“messageDecoder”,newmessagedecoder());
ch.pipeline().addLast(“frameEncoder”,新的响应句柄(Const.PACKET_HEADER_LENGTH));
ch.pipeline().addLast(“bytesEncoder”,新的ByteArrayEncoder());
ch.pipeline().addLast(getHandler());
}
}).option(ChannelOption.SO_BACKLOG,maxConnection)
.option(ChannelOption.SO_KEEPALIVE,true)
.option(ChannelOption.TCP_NODELAY,true)
.option(ChannelOption.SO_REUSEADDR,true)
.option(ChannelOption.MAX_MESSAGES_PER_READ,Integer.MAX_VALUE)
.option(ChannelOption.CONNECT\u超时\u毫秒,超时)
.option(ChannelOption.WRITE\u BUFFER\u LOW\u WATER\u MARK,32*1024)
.option(ChannelOption.WRITE\u BUFFER\u HIGH\u WATER\u MARK,128*1024)
.option(ChannelOption.ALLOCATOR,PooledByteBufAllocator.DEFAULT)
.childOption(ChannelOption.SO_KEEPALIVE,true)
.childOption(ChannelOption.TCP_NODELAY,true)
.childOption(ChannelOption.SO_REUSEADDR,true)
.childOption(ChannelOption.CONNECT\u超时\u毫秒,超时)
.childOption(ChannelOption.MAX_MESSAGES_PER_READ,Integer.MAX_VALUE)
.childOption(ChannelOption.ALLOCATOR,PooledByteBufAllocator.DEFAULT)
.childOption(ChannelOption.WRITE\u BUFFER\u LOW\u WATER\u MARK,32*1024)
.childOption(ChannelOption.WRITE\u BUFFER\u HIGH\u WATER\u MARK,128*1024);
//绑定并开始接受传入连接。
ChannelFuture f=serverBootstrap.bind(this.port.sync();
//等待服务器套接字关闭。
//在本例中,这种情况不会发生,但您可以对
//优雅地关闭服务器。
f、 通道().closeFuture().sync();
}最后{
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}捕获(可丢弃的e){
logger.error(“错误:启动Konvx服务时”,e);
}
}
@凌驾
公共无效startServer(内部端口){
super.setName(“KonvxMultimediaServer:+端口”);
this.port=端口;
这个。start();
}
@凌驾
公共void stopServer(){
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
公共请求处理程序getRequestHandler(){
返回请求处理程序;
}
public void setRequestHandler(RequestHandler RequestHandler){
this.requestHandler=requestHandler;
}
/**
*返回请求处理程序
*@returnrequesthandler
*/
私有RequestHandler getHandler(){
return(RequestHandler)beanFactory.getBean(“RequestHandler”,RequestHandler.class);
}
@凌驾
public void setBeanFactory(BeanFactory BeanFactory)抛出BeanException{
this.beanFactory=beanFactory;
}
@值(${konvx.maxConnection}”)
公共void setMaxConnection(字符串maxConnection){
this.maxConnection=Integer.parseInt(maxConnection);
}
@值(${konvx.socket.timeout}”)
公共void setTimeout(字符串超时){
this.timeout=Integer.parseInt(超时);
}
}
这是通道处理程序

public class RequestHandler extends SimpleChannelInboundHandler<KonvxMessage> {

/**
 * Logger Instance
 */
private Logger logger = Logger.getLogger(this.getClass());

@Autowired
private Router router;

@Autowired
protected UserPool userPool;

@Override
public void channelRead0(ChannelHandlerContext ctx, KonvxMessage message) throws Exception {
    Packet packet = new Packet();
    packet.setCtx(ctx);
    try {
        if (message == null) {
            logger.warn("Warning - message is empty");
            return;
        }

        // Throw the exception if in-bound message does not magic cookie
        if (!message.hasCookie()) {
            logger.error("ERROR: Bad Cookie :" + message);
            return;
        }

        // Checking if user is a valid/registered to our application
        if (!userPool.isValidUser(message.getUserId())) {
            packet.writeMessage(KonvxMessageFactory.getInvalidUserMessage(message));
            return;
        }

        packet.setInMessage(message);
        router.route(packet);
    } catch (Exception e) {
        logger.error("ERROR : Whie receiving/processing the in-bound message ", e);
        packet.writeMessage(KonvxMessageFactory.getErrorMessage(message, KonvxError.UNKNOWN_ERROR));
    }
}

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

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    logger.warn("WARN : Connection problem - " + cause.getMessage() + " Client address :" + ctx.channel().remoteAddress());
    ctx.close();
    return;
}
}
公共类RequestHandler扩展了SimpleChannelInboundHandler{
/**
*记录器实例
*/
私有记录器=Logger.getLogger(this.getClass());
@自动连线
专用路由器;
@自动连线
受保护的用户池用户池;
@凌驾
public void channelRead0(ChannelHandlerContext ctx,KonvxMessage消息)引发异常{
数据包=新数据包();
packet.setCtx(ctx);
试一试{
如果(消息==null){
logger.warn(“警告-消息为空”);
返回;
}
//如果绑定消息不存在,则引发异常
如果(!message.hascokie()){
logger.error(“错误:错误Cookie:+消息”);
返回;
}
//检查用户是否有效/已注册到我们的应用程序
如果(!userPool.isValidUser(message.getUserId())){
packet.writeMessage(KonvxMessageFactory.getInvalidUserMessage(message));
返回;
}
packet.setInMessage(消息);
路由(分组);
}捕获(例外e){
logger.error(“错误:在接收/处理绑定消息时发生”,e);
packet.writeMessage(KonvxMessageFactory.getErrorMessage(
public class MessageDecoder extends ByteToMessageDecoder {

/**
 * Logger Instance
 */
protected Logger logger = Logger.getLogger(this.getClass());

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    // Parsing the object
    String msg = null;
    try {
        byte[] bytes = new byte[in.readableBytes()];
        if (bytes.length <= 0) {
            logger.debug("Total readable bytes :" + in.readableBytes() + " exiting...");
            return;
        }

        in.readBytes(bytes);

        msg = new String(bytes, CharsetUtil.UTF_8);
        // Return if message is empty
        if (msg.isEmpty()) {
            logger.warn("Message is empty...exiting...");
            return;
        }

        KonvxMessage konvxMessage = JsonUtil.parseMessage(msg);

        // Logging the incoming message
        StringBuilder logMessage = new StringBuilder();
        logMessage.append("Incoming message :").append(System.lineSeparator())
        .append(konvxMessage)
        .append(System.lineSeparator());

        logger.info(logMessage.toString());

        out.add(konvxMessage);
    } catch (Throwable e) {
        logger.error("ERROR : While receiving/parsing/decoding the message " + msg, e);

        new Packet(ctx).writeMessage(KonvxMessageFactory.getParseFailedErrorMessage(msg));
    } 
}
}