使用文件存储的持久会话:将会话文件拆分为子目录


<Store className="org.apache.catalina.session.FileStore" directory="/somewhere/" />

如果文件夹内的文件数量增加 - 比如说到一百万(目前为 50k) - 这在 CentOS 中可能会成为一个问题?

有没有办法将会话划分为子目录?

或者这不是问题?

我想我们可以编写自己的商店 imple - 但肯定已经存在了?

问题不一定是文件系统无法处理数百万个文件。他们可以。

问题在于,通常可用于操作文件的工具很少不能很好地扩展到数百万个文件。

同时考虑lsrm

默认情况下,ls对其文件名进行排序。如果你对一个巨大的目录进行简单的ls,在扫描和排序所有这些数百万个文件时,它基本上变得无响应。你可以运行ls并告诉它不要排序,它可以工作,但它仍然很慢。

rm只是受到文件名扩展问题的困扰。现代 shell 具有非常高的基本资源可用性,但您不希望对数百万个文件运行 shell 扩展(例如"123*")。您需要跳过处理诸如findxargs之类的东西,但实际上编写自定义代码更好。

上帝禁止您在具有数百万个条目的目录中不小心在自动完成 shell 中点击 TAB。

数据库不会遇到这些问题。对数百万条记录进行表扫描是数据库的例行公事。对数以百万计的任何内容进行操作都需要时间,但数据库更适合它,尤其是像会话条目这样的小东西(假设你的会话确实很小 - 大多数都倾向于)。

JDBCStore 巧妙地绕过文件系统问题,并将负载放在更擅长处理此类卷的数据存储上。文件系统是可以制作好的、临时的"键值"存储的关键,但我们使用文件系统的大部分实际工作往往是扫描值。而且这些工具在大容量下效果不佳。

查看代码后的附录。

很容易看出为什么大型文件存储会压垮服务器。

简单地说,对于 FileStore,每次它想要尝试并使会话过期时,它都会读取整个目录。

因此,最好的情况是每分钟在 50M 文件目录中进行一次成像读取。这是不切实际的。

它不仅读取整个目录,然后继续读取目录中的每个文件,以查看它是否已过期。这也是不切实际的。50M 文件,利用一个简单的 1024 字节缓冲区来读取文件的标头,即50G的数据处理......每分钟。

这是基于乐观的假设,即它每分钟只检查一次,而不是更频繁。

相反,在 JDBCStore 中,过期时间是模型的第一类元素,因此它只返回日期小于过期时间的所有行。使用该字段上的索引,该查询基本上是即时的。更好的是,当逻辑检查会话是否确实已过期时,它只检查那些符合日期基本标准的会话,而不是每个会话。

这就是杀死你的系统的原因。

现在。

文件存储可以更好地工作吗?我不这么认为。没有简单的方法可以在文件系统中匹配通配符(我知道)。相反,所有这些匹配都是针对文件的简单"表扫描"完成的。因此,即使您认为简单地将过期时间附加到文件名的末尾很容易,但如果不扫描所有文件,您也无法找到该文件(即"查找文件名以"SESSIONID"开头的文件)。

如果会话元数据都存储在 RAM 中,则可以根据需要对其进行索引。但是,当容器重新启动时,您将面临一个丑陋的启动时间,因为它重新加载了所有延迟会话。

所以,是的,我认为在规模上,JDBCStore(或其他一些数据库/索引解决方案)是唯一真正实用的做事方法。

或者,您可以将数据库仅用于元数据,而文件存储实际会话信息。仍然需要一个数据库,但如果你不习惯将会话 BLOB 存储在数据库中,这是一个替代方案。

也许有一些特定于文件系统的实用程序可以更好地利用实际的文件系统体系结构,您可以分叉然后读取其结果(或使用 JNI 直接与 FS 通信),但显然这将非常依赖于文件系统。我对不同文件系统的底层功能并不那么熟悉。

文件夹中的大量文件是否是一个问题:是。

操作:使用 JDBCStore 而不是 FileStore。

因此,根据以下选项,开箱即用,您似乎同时获得了JDBC和基于文件的存储: Tomcat 8.5 文档,(如果您还没有在 StandardManager 和 PersistentManager 之间进行选择,请确保您阅读了该页面的所有内容)

但是我不明白为什么如果你相应地调整你的文件系统设置,基于文件的存储必须成为一个问题(至少使用 ext2/ext3/ext4 你可以,所以如果你使用 zfs、xfs、reiserfs 等,你必须查找他们的文档,但当然你可以在这个目录中挂载一个单独的磁盘(分区)它自己专门调整的文件系统参数)。

该用户发布了一些相关经验:

我刚刚用完了 4TB ext4 文件系统上目录中的文件空间, 启用dir_index。目录中有大约 1700 万个文件。 答案是用tune2fs打开large_dir。– 鲁尼克斯博克斯 2 月 6 日 在 20:09

引自:一个目录中可以放多少个文件?

有关这些文件系统可调参数(如dir_index)的更多详细信息,请参阅tune2fs 的手册页large_dir

http://man7.org/linux/man-pages/man8/tune2fs.8.html

唯一不可调的(即使使用 resize2fs 也不可调),你必须密切关注(使用:df -i)是,如果您预计在磁盘空间不足之前可能会用完许多小文件,您可能会用完 inode,因此,如果您为此制作一个特殊的文件系统,您可能需要更改默认值:

mkfs -t ext4 -N iNumberOfINodes /dev/yourstoragedevicepartition

但是,我自己还没有用Tomcat测试过所有这些,所以你可能想用Gatling,JMeter或任何其他负载测试工具测试/比较它。

当然,如果需要高可用性或零数据丢失,并且您已经有一个定期备份的 ha 数据库集群,那么 JDBC 存储可能很合适(并不是说您不能轻松地通过 NFS 将目录共享到其他 Linux 服务器,但我离题了)

最新更新