简体   繁体   English

网络中的内存问题

[英]Memory issue in netty

I am using Netty 4.0.32. 我正在使用Netty 4.0.32。 I have allocated MaxDirectMemorySize:256M 我已经分配了MaxDirectMemorySize:256M

My BootStrap is like this: 我的BootStrap是这样的:

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 SslHandler <-> ByteToMessageCodec(将ByteBuf转换为byte [],反之亦然)<-> BusinessLogicHandler

1) SslHandler for sslsupport. 1)用于sslsupport的SslHandler。 I am using java's SslEngine. 我正在使用Java的SslEngine。

2) I extend the ByteToMessageCodec like this : 2)我像这样扩展ByteToMessageCodec:

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. 3)BusinessLogicHandler将处理指定给一个线程池,该线程池执行asyncprocessing(涉及IO)并使用SocketChannel对象写回到管道。 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. 最后,我在所有写入之后添加了flush(),以便刷新所有未完成的写入。 Each write call involves a byte[] with a max size of 300bytes. 每个写调用都涉及一个byte [],最大大小为300bytes。 All the writes add upto around 20Mb totally. 所有写入的总和总计约为20Mb。

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 . 您的编码器没有尝试写入通道,而应该只是尝试将byte[]写入ByteBuf Your BusinessLogicHandler already made the decision to write or not and whether to flush or not. 您的BusinessLogicHandler已经做出是否写入以及是否刷新的决定。

Have you tried removing this code to see if it fixes your problem? 您是否尝试过删除此代码以查看它是否可以解决您的问题?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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