【问题标题】:java new File() hangs on stale NFS mount pointjava new File() 挂在过时的 NFS 挂载点上
【发布时间】:2019-06-09 06:53:07
【问题描述】:

在我的 java 代码中,我正在读取一个 NFS 挂载目录(代码在 NFS client 机器上运行)。只要 NFS 服务器机器启动并运行,一切都很好,但是当 NFS 服务器关闭时(出于任何原因),代码会挂在任何创建新文件到 nfs 挂载目录的地方。如果我只是 umount nfs 目录,我的代码运行没有问题,但我不想每天手动检查此类问题,只想在我的代码中处理这种情况

这是 NFS 服务器的 /etc/exports:

/var/nfs/general *(rw,insecure,all_squash,no_subtree_check)

实际的java代码很简单:

log.info("before new");
File file = new File("/var/nfs/general");
log.info("after new");

它只在日志文件中打印“before new”,永远不会到达“after new”

我将新文件放入 Executor 服务中,超时时间与建议的一样,但即使超时 2 秒仍会挂起:

How do I call some blocking method with a timeout in Java?

  • 操作系统:两台服务器(NFS 客户端和服务器)上的 ubuntu 服务器 16.04

    Java 版本:1.8_172

【问题讨论】:

  • 您可能希望在客户端对 NFS 驱动器进行软挂载,这样可以避免挂起,直到调用服务器备份时才挂起。
  • ServerFault SE 上的类似问题(类似答案):serverfault.com/questions/710391/nfs-server-hung-threads
  • 软挂载也没有帮助,仍然挂起
  • 嗯,有一个timeo= 值可以在您将NFS 挂载设置为软时指定,您定义了吗?否则默认值似乎是 1 分钟,这可能足以让您认为它仍然无限期挂起。如果您仍然卡住,您能否将/etc/fstab 中的相关行添加到您的问题中?编辑:此外可以有一个retrans=n(默认n=3)选项,它乘以等待读取错误的时间(超时是一次读取失败,重试最多n次读取失败)
  • 在我的测试环境中我没有使用/etc/fstab,只使用了mount命令和-o soft,intr

标签: java nfs


【解决方案1】:

您可以简单地将其包装在 Callable 下并使用 get() 并设置超时。下面是一个示例代码,如果结果(此处的文件)不可用,它会在 20 秒后超时!

FutureTask<File> futureFile = new  FutureTask<File>(new Callable<File>(){
    public File call() throws Exception {
        return new File(filePath);
    }
});

futureFile.get(20, TimeUnit.SECONDS);

出于测试目的,我已将超时设置为 3 ns。在这种情况下,文件肯定会超时。

public static File readTimeOut(final String filePath, int timeOutInMillis) throws InterruptedException, ExecutionException, TimeoutException {
        ExecutorService executor = Executors.newFixedThreadPool(1);
        FutureTask<File> futureFile = new FutureTask<File>(new Callable<File>() {

            public File call() throws Exception {
                System.out.println("I am called");
                return new File("/usr/mohamed");
            }
    });
    executor.execute(futureFile);
    return futureFile.get(3, TimeUnit.NANOSECONDS);
}

(保持一切简单。资源没有正确关闭!)但这肯定可以用 FutureTask 处理。

【讨论】:

  • 您能否在这种情况下使用我的解决方案发布堆栈跟踪和/或使用您的应用程序进行调试,以提供有关正在发生的事情的更多信息?我很确定 FutureTask 和 get() 应该可以无缝工作。
  • 我希望它也应该工作,但它只是在获取后没有移动到下一行,没有错误或异常,只是挂起。在 Intelij 上使用 Run 和 Debug 测试它
  • 那是不可能的。您确定将 FutureTask 提交给任何 ExecutorService 并调用 execute() 方法吗?请参考我的第二次编辑。
  • 在 Intelij 的 Evaluate Expression(调试模式)上调用 readTimeOut 时,它会挂起并显示结果 = 正在收集数据,但该方法适用于非远程目录
  • @f.ald 是正确的。 FutureTask 正确返回,但执行程序永远卡住了。 Afaik 对此没有解决方案,因为底层 linux 是无限阻塞的。例如,如果您 ls 共享目录,您将得到相同的结果。
猜你喜欢
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-10
  • 1970-01-01
  • 2022-07-28
相关资源
最近更新 更多