上传的文件 - 数据库和文件系统,当使用Grails和MySQL时

问题描述:

我知道这是一个“经典问题”,但mysql/grails(部署在Tomcat上)是否考虑了如何处理用户的存储上传的文件。上传的文件 - 数据库和文件系统,当使用Grails和MySQL时

我喜欢在一切中使用数据库(更简单的架构,扩展只是扩展数据库)。但是使用文件系统意味着我们不会在二进制文件中加入mysql。有些人可能会认为apache(httpd)比Tomcat更快地提供二进制文件,尽管我已经看到实际上只显示将Tomcat放在网站前面的数字可能比使用apache(httpd)代理更快。

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

感谢您的考虑,时间和想法。

我不知道是否可以对此类决策进行一般性观察,因为这确实取决于您正在尝试执行的操作,以及优先级列表NFR(如性能和响应时间)对您的应用程序有多高。

如果你有很多用户,上传大量的二进制文件,以服务于大量的上传的二进制文件,那么你有一个情况,其中在数据库中存储文件的成本包括系统:

  • 大尺寸的二进制文件
  • 开销查询

好处是

  • 原子提交
  • 缩放自带数据库(虽然W¯¯的MySQL也有一些问题W¯¯多节点等)
  • 较少繁琐和复杂的代码来管理文件系统等

考虑您存储到同一个用户的情况文件系统,你将需要解决

  • 缩放
  • 文件名管理(用户上传的同名文件两次等)
  • 创建在DB相应的记录以映射到磁盘上(周围的一切和代码)的文件
  • 你的apache的configs后寻找使他们从文件系统

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

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

我们很难确保图像重新同步到每个服务器上,因为与位于群集后面的DB不同,并且使群集的行为一致,文件被绑定到服务器上的物理位置。

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

我暗示的是虽然我们通过不使用数据库来获得BLOB存储的性能,但这是以开发开销和系统管理为代价的。

正如其他建议:JCR(例如,Jackrabbit) - 一个Java内容存储库。处理大量二进制内容时,它有几个好处。 Grails插件尚不稳定,但您可以使用简单的API使用Jackrabbit。

+0

哦,这听起来不错... :) – 2009-01-29 16:26:38

要记住的另一件事是,如果您的网站超出一台应用程序服务器,则需要从所有应用程序服务器访问相同的文件。现在所有的应用程序服务器都可以访问数据库,因为这是一台服务器或者您拥有一个集群。现在,如果您将文件存储在文件系统中,则还必须共享该文件 - 也许是NFS。

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