3

我知道这是一个“经典问题”,但是 mysql/grails(部署在 Tomcat 上)是否在考虑如何处理用户上传文件的存储方面产生了新的变化。

我喜欢将数据库用于一切(更简单的架构,扩展只是扩展数据库)。但是使用文件系统意味着我们不会用二进制文件来处理 mysql。有些人可能还争辩说 apache (httpd) 在提供二进制文件方面比 Tomcat 更快,尽管我看到的数字实际上表明将 Tomcat 放在您的网站前面可能比使用 apache (httpd) 代理更快。

我应该如何选择放置用户上传文件的位置?

感谢您的考虑、时间和思考。

4

4 回答 4

5

我不知道是否可以对这种决定进行一般性观察,因为这实际上取决于您要做什么以及优先级列表 NFR(例如性能和响应时间)对您的应用程序的影响。

如果您有很多用户,上传大量二进制文件,并且系统为大量上传的二进制文件提供服务,那么您会遇到在数据库中存储文件的成本包括:

  • 大尺寸二进制文件
  • 昂贵的查询

好处是

  • 原子提交
  • 扩展随数据库一起提供(尽管使用 MySQL,但使用多节点等存在一些问题)
  • 管理文件系统等的繁琐和复杂的代码

鉴于您存储到文件系统的相同用户情况,您需要解决

  • 缩放
  • 文件名管理(用户上传同名文件两次等)
  • 在数据库中创建相应的记录以映射到磁盘上的文件(以及围绕所有这些的代码)
  • 照顾您的 apache 配置,以便它们从文件系统提供服务

对于我们的 Grails 站点,我们有一个类似的问题需要解决,其中内容编辑器每天要上传数百张图片。我们知道,当应用程序可以更好地用于其他处理时,通过应用程序驱动所有需求是浪费的(考虑到对页面的预期需求将达到每周数百万,我们绝对不希望图像削弱我们)。

我们最终创建了上传 -> 文件系统解决方案。对于每个上传的文件,都会创建一个 DB 元数据记录并与上传过程一起管理(相反,在生成图像的 GSP 内容链接时读取该记录)。我们根据浏览器请求的链接直接通过 Apache 提供磁盘请求。但是,总是有一个但是,请记住,对于文件系统之类的东西,每台机器只有内容。

我们为确保图像重新同步到每台服务器上而感到头疼,因为与位于集群后面并支持集群行为一致的数据库不同,文件绑定到服务器上的物理位置。

文件系统可能遇到的另一个问题是文件夹内容大小。当您开始拥有包含数以万计文件的文件夹时,操作系统级别的文件夹扫描开始真正拖累。为了避免这个问题,我们必须编写代码来管理图像上传到 yyyy/MM/dd/image.name.jpg 文件夹结构中,这样没有一个文件夹会累积数十万张图像。

我的意思是,虽然我们通过不将数据库用于 BLOB 存储而获得了我们想要的性能,但这是以开发开销和系统管理为代价的。

于 2009-01-29T16:00:55.137 回答
3

就像一个额外的建议:JCR(例如Jackrabbit) - Java 内容存储库。当您处理大量二进制内容时,它有几个好处。Grails 插件还不稳定,但您可以将 Jackrabbit 与普通 API 一起使用。

于 2009-01-29T16:24:25.557 回答
0

要记住的另一件事是,如果您的站点超出了一个应用程序服务器,您需要从所有应用程序服务器访问相同的文件。现在所有应用服务器都可以访问数据库,因为那是单个服务器,或者因为您有一个集群。现在,如果您将内容存储在文件系统中,您也必须共享它——也许是 NFS。

于 2009-02-05T13:46:35.667 回答
0

即使您在文件系统中上传文件,所有文件都获得相同的权限,因此任何登录用户只需输入 url 即可访问任何其他人的文件(因为他们都获得相同的权限)。但是,如果您计划为每个用户提供一个目录,那么将授予他们 apache 的用户权限(即服务器具有的权限)。您应该 su 到 root,创建​​一个用户并将文件上传到这些目录。再次访问这些文件可能最终会将用户组添加到服务器组。如果我选择使用文件系统来存储二进制文件,有没有比这更简单的解决方案,你如何管理对这些文件的访问,对应每个用户,并维护权限?Spring 的 ACL 有帮助吗?还是我们必须为每个用户创建权限组?我对文件系统 url 非常满意。我唯一关心的是启动一个单独的进程(chmod 和其他东西),使用 ProcessBuilder 之类的东西来运行操作系统命令(或者有更好的解决方案吗?)。那么权限呢?

于 2011-12-01T02:22:13.077 回答