繁体   English   中英

由于网络中断后锁定nfs文件导致JVM崩溃

[英]JVM crash because of lock on nfs file after network outage

以下代码片段导致JVM崩溃:如果获取锁定后发生网络中断

    while (true) {

       //file shared over nfs
       String filename = "/home/amit/mount/lock/aLock.txt";
       RandomAccessFile file = new RandomAccessFile(filename, "rws");
       System.out.println("file opened");
       FileLock fileLock = file.getChannel().tryLock();
       if (fileLock != null) {
          System.out.println("lock acquired");
       } else {
          System.out.println("lock not acquired");
       }

       try {
          //wait for 15 sec
          Thread.sleep(30000);
       } catch (InterruptedException e) {
          e.printStackTrace();
       }
       System.out.println("closing filelock");
       fileLock.close();
       System.out.println("closing file");
       file.close();
    }

观察:JVM接收KILL(9)信号并退出,退出代码为137(128 + 9)。

可能在网络连接重建之后,文件描述符表中出现了问题。 使用系统调用flock(2)和shell实用程序flock(1)可以重现此行为。

任何建议/解决方案?

PS:将Oracle JDK 1.7.0_25与NFSv4一起使用

编辑 :此锁定将用于标识分布式高可用性集群中哪个进程处于活动状态。 退出代码是137.我期待什么? 检测问题的方法。 关闭文件并尝试重新获取。

退出代码138没有暗示SIGKILL - 这是信号10,可以是SIGBUS(在solaris上)或SIGUSR1(在linux上)。 不幸的是,你没有告诉我们你正在使用哪一个。

从理论上讲,nfs应该透明地处理所有事情 - 机器崩溃,重新启动并清除锁。 在实践中,我从来没有在NFS3中看到过这种工作,而NFS4(你正在使用它)使事情变得更加困难,因为没有单独的lockd()和statd()。

我建议你在java进程上运行truss(solaris)或strace(linux),然后拔出网络插件,找出真正发生的事情。 但说实话,只要我使用Unix(超过25年),人们就建议不要锁定NFS文件系统,我强烈建议你编写一个小型服务器程序来处理“谁做了什么“事情。 让您的客户端连接到服务器,让他们向服务器发送一些“以X开头”和“停止执行X”消息,如果客户端的回答超过,请让服务器正常超时连接。 5分钟。 我99%肯定这会比你尝试修复NFS锁定花费更少的时间。

NFS服务器重新启动后,所有具有任何活动文件锁定的客户端都会启动锁定回收过程,该过程持续时间不超过所谓的“宽限期”(仅为常量)。 如果回收过程在宽限期内失败,则NFS客户端(通常是内核空间野兽)会将SIGUSR1发送到无法恢复其锁定的进程。 这是你问题的根源。

当服务器端的锁成功时,客户端系统上的rpc.lockd请求另一个守护程序rpc.statd来监视实现锁的NFS服务器。 如果服务器出现故障然后恢复,将通知rpc.statd。 然后它尝试重新建立所有活动锁。 如果NFS服务器出现故障并恢复,并且rpc.lockd无法重新建立锁定,它会向请求锁定的进程发送信号(SIGUSR1)。

http://menehune.opt.wfu.edu/Kokua/More_SGI/007-2478-010/sgi_html/ch07.html

你可能想知道如何避免这种情况。 嗯,有几种方法,但没有一种是理想的:

  1. 增加宽限期。 AFAIR,在linux上可以通过/ proc / fs / nfsd / nfsv4leasetime进行更改。
  2. 在代码中创建一个SIGUSR1处理程序并在那里做一些聪明的事情。 例如,在信号处理程序中,您可以设置一个标志,表示锁定恢复失败。 如果设置了此标志,则程序可以尝试等待NFS服务器的准备就绪(只要它需要),然后它可以尝试自己恢复锁。 效果不佳......
  3. 不要再使用NFS锁定。 如果可以像之前建议的那样切换到zookeeper。

使用系统调用flock(2)和shell实用程序flock(1)可以重现此行为。

由于您能够在Java之外重现它,这听起来像是基础设施问题。 您没有在NFS服务器或客户端操作系统上提供太多信息,但我看到的一件事导致NFS的奇怪行为是错误的DNS配置。

检查客户端上“uname -n”和“hostname”的输出是否与DNS记录匹配。 检查NFS服务器是否正确解析DNS。

像Guntram一样,我也建议不要使用NFS来做这类事情。 我会使用Hazlecast (没有服务器,实例动态集群)或ZooKeeper (需要设置服务器)。

使用Hazlecast,您可以执行此操作以获得独有的群集范围锁:

import com.hazelcast.core.Hazelcast;
import java.util.concurrent.locks.Lock;

Lock lock = Hazelcast.getLock(myLockedObject);
lock.lock();
try {
    // do something here
} finally {
    lock.unlock();
} 

它还支持超时:

if (lock.tryLock (5000, TimeUnit.MILLISECONDS)) {
    try {  
       // do some stuff here..  
   } 
    finally {  
      lock.unlock();  
    }   
} 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM