简体   繁体   中英

Memory issue in netty

I am using Netty 4.0.32. I have allocated MaxDirectMemorySize:256M

My BootStrap is like this:

bootStrap = new ServerBootstrap();
childGroup = new NioEventLoopGroup();
bootStrap.localAddress(protocolConstant.getPort());
bootStrap.channel(NioServerSocketChannel.class);
bootStrap.group(PARENTGROUP, childGroup);
bootStrap.childHandler(new MailChannelInitializer());
bootStrap.option(ChannelOption.SO_BACKLOG, BACKLOG);
bootStrap.childOption(ChannelOption.AUTO_READ, true);
bootStrap.childOption(ChannelOption.MAX_MESSAGES_PER_READ, 1 * 1024);
bootStrap.childOption(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, 512);
bootStrap.childOption(ChannelOption.WRITE_BUFFER_LOW_WATER_MARK, 256);
bootStrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

My pipeline looks like this:

SslHandler <-> ByteToMessageCodec(tranforms the ByteBuf to byte[] and vice versa) <-> BusinessLogicHandler

1) SslHandler for sslsupport. I am using java's SslEngine.

2) I extend the ByteToMessageCodec like this :

private class ByteConversionCodec extends ByteToMessageCodec<byte[]> {

    @Override
    protected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out)
            throws Exception {
        if (!ctx.channel().isWritable()) {
            ctx.flush();
        }
        out.writeBytes(msg);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in,
            List<Object> out) throws Exception {
        byte[] arr;
        if (in.hasArray()) {
            arr = in.array();
        }
        else {
            arr = new byte[in.readableBytes()];
            in.readBytes(arr);
        }
        out.add(arr);
    }

}

If the channel is not writable when calling encode, I add a flush request so that the channel becomes writable again. Is this correct?

3) The BusinessLogicHandler designates the processing to a thread pool which does asyncprocessing(involves IO) and writes back to the pipeline using the SocketChannel object. All the writes are originated from the thread pool. And finally I add a flush() after all the writes so that all pending writes are flushed. Each write call involves a byte[] with a max size of 300bytes. All the writes add upto around 20Mb totally.

Thread [nioEventLoopGroup-3-1] (Suspended)  
    Thread.sleep(long) line: not available [native method]  
    Bits.reserveMemory(long, int) line: 651 
    DirectByteBuffer.<init>(int) line: 123  
    ByteBuffer.allocateDirect(int) line: 306    
    PoolArena$DirectArena.newChunk(int, int, int, int) line: 645    
    PoolArena$DirectArena(PoolArena<T>).allocateNormal(PooledByteBuf<T>, int, int) line: 228    
    PoolArena$DirectArena(PoolArena<T>).allocate(PoolThreadCache, PooledByteBuf<T>, int) line: 212  
    PoolArena$DirectArena(PoolArena<T>).allocate(PoolThreadCache, int, int) line: 132   
    PooledByteBufAllocator.newDirectBuffer(int, int) line: 271  
    PooledByteBufAllocator(AbstractByteBufAllocator).directBuffer(int, int) line: 155   
    PooledByteBufAllocator(AbstractByteBufAllocator).directBuffer(int) line: 146    
    PooledByteBufAllocator(AbstractByteBufAllocator).buffer(int) line: 83   
    SslHandler.allocate(ChannelHandlerContext, int) line: 1504  
    SslHandler.allocateOutNetBuf(ChannelHandlerContext, int) line: 1514 
    SslHandler.wrap(ChannelHandlerContext, boolean) line: 517   
    SslHandler.flush(ChannelHandlerContext) line: 500   
    DefaultChannelHandlerContext(AbstractChannelHandlerContext).invokeFlush() line: 663 
    DefaultChannelHandlerContext(AbstractChannelHandlerContext).flush() line: 644   
    Server$MailChannelInitializer$ByteConversionCodec.encode(ChannelHandlerContext, byte[], ByteBuf) line: 134  
    Server$MailChannelInitializer$ByteConversionCodec.encode(ChannelHandlerContext, Object, ByteBuf) line: 1    
    ByteToMessageCodec$Encoder.encode(ChannelHandlerContext, I, ByteBuf) line: 168  
    ByteToMessageCodec$Encoder(MessageToByteEncoder<I>).write(ChannelHandlerContext, Object, ChannelPromise) line: 107  
    Server$MailChannelInitializer$ByteConversionCodec(ByteToMessageCodec<I>).write(ChannelHandlerContext, Object, ChannelPromise) line: 108 
    DefaultChannelHandlerContext(AbstractChannelHandlerContext).invokeWrite(Object, ChannelPromise) line: 633   
    AbstractChannelHandlerContext.access$1900(AbstractChannelHandlerContext, Object, ChannelPromise) line: 32   
    AbstractChannelHandlerContext$WriteTask(AbstractChannelHandlerContext$AbstractWriteTask).write(AbstractChannelHandlerContext, Object, ChannelPromise) line: 908 
    AbstractChannelHandlerContext$WriteTask(AbstractChannelHandlerContext$AbstractWriteTask).run() line: 893    
    NioEventLoop(SingleThreadEventExecutor).runAllTasks(long) line: 358 
    NioEventLoop.run() line: 357    
    SingleThreadEventExecutor$2.run() line: 112 
    DefaultThreadFactory$DefaultRunnableDecorator.run() line: 137   
    FastThreadLocalThread(Thread).run() line: 745   

Because of this I find a delay in getting the content. The thread sleeps for a while to get the memory. Could anyone kindly help me with this situation? Thank you.

If the channel is not writable when calling encode, I add a flush request so that the channel becomes writable again. Is this correct?

That doesn't look right to me. Your encoder isn't trying to write to the channel, it should just be trying to byte[] into a ByteBuf . Your BusinessLogicHandler already made the decision to write or not and whether to flush or not.

Have you tried removing this code to see if it fixes your problem?

if (!ctx.channel().isWritable()) {
    ctx.flush();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM