Java Gridgain 应用程序在压力测试 1 天后开始失败

标签 java testing fileinputstream stress gridgain

所以我有一个在 gridgain 之上运行的应用程序,并且在它开始表现得很滑稽之前进行了大约 12-24 小时的压力测试,并且非常成功。这段时间过后,应用程序将突然开始回复所有异常 java.nio.channels.ClosedByInterruptException 的查询(完整堆栈跟踪位于 http://pastie.org/664717

失败的方法是(编辑为使用@stephenc 反馈)

public static com.vlc.edge.FileChannel createChannel(final File file) {
    FileChannel channel = null;
    try {
    channel = new FileInputStream(file).getChannel();
    channel.position(0);
    final com.vlc.edge.FileChannel fileChannel = new FileChannelImpl(channel);
    channel = null;
    return fileChannel;
    } 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 (IOException e){
        // noop
        LOGGER.error("There was a problem closing the file: " + file);
        }
    }
    }
}

并且调用函数正确地关闭了对象

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 个此类 channel )。似乎在一段时间后它无法打开文件,我无法解释为什么会发生这种情况,如果有人能告诉我可能导致这种情况的原因以及我如何进行跟踪,我将不胜感激它下来并修复它。如果它可能与文件句柄耗尽有关,我很想听听任何确定确定的提示......即在运行时查询 JVM 或使用 linux 命令行工具来查找有关当前打开的句柄的更多信息.

更新:我一直在使用命令行工具来查询 lsof 的输出,但未能看到文件句柄保持打开状态的任何证据......网格具有非常稳定的打开文件配置文件,我可以看到随着上述代码的执行而发生变化......但它总是返回到稳定数量的打开文件。

与此问题相关:Freeing java file handles

最佳答案

有几种情况可能无法关闭文件句柄:

  1. 可能还有一些其他代码可以打开文件。
  2. 可能还有其他一些代码调用了 createChannel(...) 而没有调用 fillContactBuffer(...)
  3. 如果channel.position(0) 抛出异常, channel 不会关闭。解决方法是重新排列代码,使以下语句位于 try block 内。

    channel.position(0);
    return new FileChannelImpl(channel);
    

编辑:查看堆栈跟踪,这两种方法似乎在不同的代码库中。我会将责任归咎于 createChannel 方法。它可能会泄漏,即使它不是问题的根源。它需要一个内部 finally 子句来确保在发生异常时关闭 channel 。

像这样的东西应该可以解决问题。请注意,您需要确保 finally block 不会在成功时关闭 channel !

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 调用通过抛出异常来响应中断,这里抛出的根异常看起来就像这样一个异常。

这并不能解释为什么会发生这种情况,但我粗略地猜测,这是服务器端框架试图解决过载或死锁问题。

关于Java Gridgain 应用程序在压力测试 1 天后开始失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1605522/

相关文章:

java.sql.SQLException : Incorrect string value: '\xF0\x9F\x91\xBD\xF0\x9F...'

laravel - 如何测试从 Laravel 中的通知发送的邮件

java - 向 Scoreloop 提交较小的结果

python - 什么是行业广泛使用的持续集成工具,基于 Python 的程序的夜间构建系统

用于使用 anchor 进行查询的 javascript 正则表达式

Web 服务中的 Java FileInputStream

C++如何读取具有给定偏移量的对象?

java - 未处理的异常类型filenotfoundException,编译问题

java字符转换为二维字符数组中的数字

java - 如何通过ASM捕获字节码中的运行时异常