[英]Accumulating Netty direct IO buffer to CompositeByteBuf
We are migrating from Servlet API 2.5 (thread per request) in our application to Netty. 我们正在从应用程序中的Servlet API 2.5(每个请求的线程)迁移到Netty。 One of cases is using blocking-style ini file parser which we had for many years.
一种情况是使用我们拥有多年的阻塞式ini文件解析器。 Current approach is accumulating incoming
ByteBuf
into CompositeByteBuf
and feeding it to a parser after wrapping with ByteBufInputStream
. 当前的方法是将传入的
ByteBuf
累积到CompositeByteBuf
并在用ByteBufInputStream
包装之后将其提供给解析器。
In real application we are using HTTP and ini is sent to a server as HTTP request body. 在实际的应用程序中,我们使用HTTP,并且ini作为HTTP请求正文发送到服务器。 But in snippet below it is assumed that all inbound content is transferred file.
但在下面的代码段中,假定所有入站内容都是传输文件。
class AccumulatingChannelHandler extends ChannelInboundHandlerAdapter {
final BlockingIniFileParser parser = new BlockingIniFileParser();
CompositeByteBuf accumulator;
@Override
public void channelActive(ChannelHandlerContext ctx) {
accumulator = ctx.alloc().compositeBuffer(Integer.MAX_VALUE);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf ioBuffer = (ByteBuf) msg;
accumulator.addComponent(true, ioBuffer);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
IniFile iniFile = parser.parse(new ByteBufInputStream(accumulator));
accumulator.release();
ByteBuf result = process(iniFile);
ctx.writeAndFlush(result);
ctx.close();
}
private ByteBuf process(IniFile iniFile) {...}
}
class BlockingIniFileParser {
IniFile parse(InputStream in) {...}
}
interface IniFile {
String getSetting(String section, String entry);
}
By default pooled direct buffers are coming to channelRead
method. 默认情况下,池直接缓冲区进入
channelRead
方法。 And with such strategy we risk to get uncontrollable consumption of direct memory. 使用这种策略,我们可能会面临无法控制的直接内存消耗。 So, I would like to understand:
因此,我想了解:
You have not mentioned the size of a typical uploaded ini file, but assuming they're large enough to cause some concern, I would consider ditching the CompositeByteBuf. 您没有提到典型的上载ini文件的大小,但是假设它们足够大以至于引起一些关注,我将考虑放弃CompositeByteBuf。 Allocate an un-pooled [optionally direct] buffer and as pooled buffers come in the door, write them to the un-pooled buffer, then release them.
分配一个非池化的(可选直接)缓冲区,并在池中的缓冲区进入门中时,将其写入非池化缓冲区中,然后释放它们。 When you're done reading, continue with your use of a ByteBufInputStream around the un-pooled buffer.
阅读完毕后,继续在未池缓冲的缓冲区周围使用ByteBufInputStream。 Once complete, the un-pooled buffer will be GCed.
完成后,未缓冲的缓冲区将被GC化。
You will still be allocating chunks of memory, but it won't be drawn from your buffer pools, and if you use a direct un-pooled buffer, it will not impact your heap as much. 您仍将分配内存,但是不会从缓冲池中提取内存,如果您使用直接的非池缓冲,则不会对堆造成太大影响。
Ultimately, if the size of the un-pooled buffer remains a concern, I would bite the bullet and write the incoming pooled buffers out to disk and on completion, read them back in using a FileInputStream. 最终,如果未缓冲的缓冲区的大小仍然值得关注,我会咬牙切齿,将传入的缓冲池写到磁盘上,并在完成后使用FileInputStream读回它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.