Java Gridgain应用程序在1天的压力测试后开始失败
所以我有一个在gridgain上运行的应用程序,在它开始变得有趣之前,它成功地进行了大约12-24小时的压力测试。在这段时间之后,应用程序将突然开始响应所有查询,异常为java.nio.channels.ClosedByInterruptException(完整堆栈跟踪位于 失败的方法是(编辑为使用@stephenc feedback) 并且调用函数正确地关闭对象Java Gridgain应用程序在1天的压力测试后开始失败,java,testing,fileinputstream,stress,gridgain,Java,Testing,Fileinputstream,Stress,Gridgain,所以我有一个在gridgain上运行的应用程序,在它开始变得有趣之前,它成功地进行了大约12-24小时的压力测试。在这段时间之后,应用程序将突然开始响应所有查询,异常为java.nio.channels.ClosedByInterruptException(完整堆栈跟踪位于 失败的方法是(编辑为使用@stephenc feedback) 并且调用函数正确地关闭对象 private void fillContactBuffer(final File signFile) { contactB
private void fillContactBuffer(final File signFile) {
contactBuffer = ByteBuffer.allocate((int) signFile.length());
final FileChannel channel = FileUtils.createChannel(signFile);
try {
channel.read(contactBuffer);
} finally {
channel.close();
}
contactBuffer.rewind();
}
该应用程序基本上充当一个分布式文件解析器,因此它执行许多此类操作(通常每个节点每个查询打开大约10个这样的通道)。似乎过了一段时间它就无法打开文件了,我无法解释为什么会发生这种情况,如果有人能告诉我是什么原因导致了这种情况,我将非常感激。如果这可能与文件句柄耗尽有关,我希望能听到一些有关的提示确定查找…即在JVM运行时查询JVM,或使用linux命令行工具查找有关当前打开的句柄的更多信息
更新:我一直在使用命令行工具查询lsof的输出,但没有看到文件句柄处于打开状态的任何证据……网格中的每个节点都有一个非常稳定的打开文件配置文件,我可以看到随着上述代码的执行而发生变化……但它总是返回到一个稳定数量的open文件
与此问题相关:有两种情况下可能无法关闭文件句柄:
createChannel(…)
而不调用fillContactBuffer(…)
channel.position(0)
抛出异常,则通道将不会关闭。修复方法是重新排列代码,使以下语句位于try
块内
channel.position(0);
return new FileChannelImpl(channel);
createChannel
方法。它可能存在泄漏,即使它不是问题的根源。它需要一个in internalfinally
子句,以确保在f例外
类似这样的操作应该可以做到。请注意,您需要确保finally
块在成功时不会关闭频道
public static com.vlc.edge.FileChannel createChannel(final File file) {
final FileChannel channel = null;
try {
channel = new FileInputStream(file).getChannel();
channel.position(0);
FileChannel res = new FileChannelImpl(channel);
channel = null;
return res;
} catch (FileNotFoundException e) {
throw new VlcRuntimeException("Failed to open file: " + file, e);
} catch (IOException e) {
throw new VlcRuntimeException(e);
} finally {
if (channel != null) {
try {
channel.close();
} catch (...) {
...
}
}
}
}
跟进很久以后 考虑到文件句柄泄漏已被排除为可能的原因,我的下一个理论是服务器端实际上正在使用
Thread.interrupt()中断自己的线程
。一些低级I/O调用通过抛出异常来响应中断,这里抛出的根异常看起来像这样的异常
这并不能解释为什么会发生这种情况,但我猜测是服务器端框架试图解决过载或死锁问题
public static com.vlc.edge.FileChannel createChannel(final File file) {
final FileChannel channel = null;
try {
channel = new FileInputStream(file).getChannel();
channel.position(0);
FileChannel res = new FileChannelImpl(channel);
channel = null;
return res;
} catch (FileNotFoundException e) {
throw new VlcRuntimeException("Failed to open file: " + file, e);
} catch (IOException e) {
throw new VlcRuntimeException(e);
} finally {
if (channel != null) {
try {
channel.close();
} catch (...) {
...
}
}
}
}