问题:
我有一个运行 Java 应用程序的 Tomcat,它偶尔会累积套接字句柄并达到我们为 max-open-files 配置的 ulimit(软和硬),即 100K。发生这种情况时,Java 似乎仍处于活动状态,但我们无法再访问它。
然而我的问题是关于这种情况伴随的一个奇怪现象:我无法mkdir
进入 tomcat 文件夹。
[root@server /opt/apache-tomcat-7.0.52]# mkdir some_folder
mkdir: cannot create directory `some_folder': No space left on device
事实上,我在 下的多个不同文件夹下都遇到了同样的错误/opt
,但这些文件夹并不/opt
直接位于 下,也不位于(例如) 下/opt/apache-tomcat-7.0.52/logs
。
我无论如何都无法解释,只能使用 来解决init 6
。有什么建议可以解决这个问题,并且mkdir
无需重启即可再次运行?
我收集的一些指针和线索:
该设置是在 AWS 下运行的 CentOS 6.5,并从 EBS 卷安装所述 tomcat 磁盘。
运行df -h
表明磁盘显然没有满:
[root@server ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 9.9G 3.6G 5.9G 38% /
none 121G 0 121G 0% /dev/shm
/dev/xvdc 1008G 197G 760G 19% /mnt/eternal
内容/etc/fstab
(由于某种原因,使用双重安装 - 不确定为什么):
/dev/xvdc /mnt/eternal ext4 defaults 0 0
/mnt/eternal /opt ext4 defaults,bind 0 0
以及来自以下的相应行mount
:
/dev/xvdc on /mnt/eternal type ext4 (rw)
/mnt/eternal on /opt type none (rw,bind)
跑步df -i
并不暗示有什么不好的事情(并且与健康的系统相似):
[root@server ~]# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/xvda1 655360 78245 577115 12% /
none 31549847 1 31549846 1% /dev/shm
/dev/xvdc 67108864 12551 67096313 1% /mnt/eternal
运行sysctl fs.file-nr
结果显然很高,但似乎远非极限:
[root@server ~]# sysctl fs.file-nr
fs.file-nr = 101632 0 25087252
运行find /proc | wc -l
返回62497876
(62M),这可能会达到某些操作系统的限制;在类似的健康系统上,它更像是 1800000(1.8M)。
占用空间巨大的子文件夹似乎是/proc/<my-java-pid>/task
(约 62M 个项目,而健康系统上约 1.7M 个项目)。这可能只是我的 100K fds(x2,对于 fds 和 fdinfos)在 300 个单独的“任务”文件夹中的体现。
这出现在我的 dmesg 转储的末尾(本例中我的 java pid 是 105940) - 不确定这可能有何关联:
INFO: task java:105940 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
java D 0000000000000008 0 105940 1 0x00000080
ffff88161ab55c88 0000000000000082 ffff88161ab55c18 ffffffff8109be4f
ffffffff81ed28f0 ffff881e66360ae0 ffffffff8100bb8e ffff88161ab55c88
ffff881e66361098 ffff88161ab55fd8 000000000000fb88 ffff881e66361098
Call Trace:
[<ffffffff8109be4f>] ? hrtimer_try_to_cancel+0x3f/0xd0
[<ffffffff8100bb8e>] ? apic_timer_interrupt+0xe/0x20
[<ffffffff810521c9>] ? mutex_spin_on_owner+0x99/0xc0
[<ffffffff8151636e>] __mutex_lock_slowpath+0x13e/0x180
[<ffffffff8151620b>] mutex_lock+0x2b/0x50
[<ffffffff8111c461>] generic_file_aio_write+0x71/0x100
[<ffffffffa0121fb1>] ext4_file_write+0x61/0x1e0 [ext4]
[<ffffffff81180d7a>] do_sync_write+0xfa/0x140
[<ffffffff81096ca0>] ? autoremove_wake_function+0x0/0x40
[<ffffffff812292ab>] ? selinux_file_permission+0xfb/0x150
[<ffffffff8121bd26>] ? security_file_permission+0x16/0x20
[<ffffffff81181078>] vfs_write+0xb8/0x1a0
[<ffffffff81181971>] sys_write+0x51/0x90
[<ffffffff81517e2e>] ? do_device_not_available+0xe/0x10
[<ffffffff8100b072>] system_call_fastpath+0x16/0x1b
我很乐意分享/提供任何其他建议的发现。
我暗自希望了解这种怪异行为能揭示导致整个混乱的病因。但这只是我个人的希望 :)
答案1
在大多数情况下(显然不是您的情况),原因是您用完了 iNode。
要检查此运行 df -i:
Filesystem Inodes IUsed IFree IUse% Mounted on
[...]
25600 25600 0 100% /foo
这里您可以看到 iNode 的使用率为 100%。
坏消息是,根据https://superuser.com/questions/585641/changing-max-inode-count-number-in-ext3-filesystem-in-cent-os您需要使用 -i 选项重新创建文件系统,以增加 inode 的数量。
答案2
我找到了“如何解决这种情况”这个问题的答案。我不知道这件事发生的所有细节,但我知道的足以给出答案。
简短回答:卸载磁盘,chkdsk -f
在其上运行,然后重新安装可以解决并防止问题再次发生。作为替代方案,创建一个新磁盘(记住我们在 AWS 上)并将所有数据复制到新磁盘(这rsync -a
是我选择的命令)并使用它来替换原始磁盘也可以解决和防止问题。
较长的答案:磁盘文件系统 (ext4) 在最初创建磁盘快照时似乎已达到某种不稳定状态。当后来将 200GB 的原始快照扩展(使用resize2fs
)到 1TB 时,似乎在某种意义上它一直在内部记住 200GB 的原始大小,从而产生各种奇怪的现象,最终导致操作系统无法关闭句柄,从而使 Tomcat 达到其文件限制,从而导致一切都崩溃。
这是最长的答案,包含更多侦查工作细节:当我们在两个不同的设置上同时发生这种病症时,我们取得了突破。检查这些设置上的所有参数并进行比较后,我们意识到df -h
驱动器上显示的是以下结果:
/dev/xvdc 1008G 197G 760G 19% /mnt/eternal
现在,这之前并没有引起我们的注意,因为磁盘仍然有足够的空间。但两个设置上的磁盘使用量完全相同(197G),这没有理由发生。从这里开始,事情很快就展开了。如前所述,我们的 AWS 实例是从具有 200GB 磁盘快照的映像创建的,该映像在单个实例上使用时会扩展resize2fs
- 通常最大大小为 1TB。我们最终能够通过启动新实例、调整为 1TB 并创建一个 300GB 的大文件来重新创建“坏状态”。完成后,系统没有冻结,但确实表现出相同的奇怪行为:
/dev/xvdc 1008G 197G 760G 19% /mnt/eternal
并且磁盘上的数据显然超过 197GB。因此,我们在两个单独的干净设置上尝试了上述两种方法(chkdsk 和重新创建磁盘),在每个设置上都不再出现奇怪的行为。
我们最好的猜测是,在创建 AMI 的某个时刻,快照过程中出现了问题 - 最有可能是因为我们拍摄了“未重启快照”(虽然我们通常不会这样做,而且我也没有证据支持这一点,所以我希望我们的 DevOps 不会因为我无缘无故地责怪她而生我的气!)。总而言之,这是一次有趣的经历。