[英]Accumulating Netty direct IO buffer to CompositeByteBuf
我们正在从应用程序中的Servlet API 2.5(每个请求的线程)迁移到Netty。 一种情况是使用我们拥有多年的阻塞式ini文件解析器。 当前的方法是将传入的ByteBuf
累积到CompositeByteBuf
并在用ByteBufInputStream
包装之后将其提供给解析器。
在实际的应用程序中,我们使用HTTP,并且ini作为HTTP请求正文发送到服务器。 但在下面的代码段中,假定所有入站内容都是传输文件。
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);
}
默认情况下,池直接缓冲区进入channelRead
方法。 使用这种策略,我们可能会面临无法控制的直接内存消耗。 因此,我想了解:
您没有提到典型的上载ini文件的大小,但是假设它们足够大以至于引起一些关注,我将考虑放弃CompositeByteBuf。 分配一个非池化的(可选直接)缓冲区,并在池中的缓冲区进入门中时,将其写入非池化缓冲区中,然后释放它们。 阅读完毕后,继续在未池缓冲的缓冲区周围使用ByteBufInputStream。 完成后,未缓冲的缓冲区将被GC化。
您仍将分配内存,但是不会从缓冲池中提取内存,如果您使用直接的非池缓冲,则不会对堆造成太大影响。
最终,如果未缓冲的缓冲区的大小仍然值得关注,我会咬牙切齿,将传入的缓冲池写到磁盘上,并在完成后使用FileInputStream读回它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.