如何在Heroku多个dynos上使用carrierwave缓存?

4
我在Heroku上有一个带有Carrierwave的应用程序。在页面上,我有两个表单:一个ajax表单用于上传图片,另一个普通表单用于创建对象所需的其他信息。假设我的Carrierwave安装是:picture,每次提交ajax表单时,图片会暂时保存到公共文件夹中,并返回其路径为:picture_cache。然后,第二个表单使用它来知道要在第二个请求中使用哪个图片来创建新对象。这对于一个单独的dyno很有效。
不同的dyno不知道彼此的文件系统。因此,如果提交第二个表单的请求没有命中与第一个表单请求相同的dyno,则无法找到该图片。
有人解决过这个问题吗?

你解决过这个问题吗?而不必使用Mongoid吗? - stephenmurdoch
1个回答

2
我使用自定义模型并将所有文件(包括临时文件)存储在MongoDB中。上传的文件被标记为tmp。一旦模型被“保存”,我就会简单地删除“tmp”标志。通过这种方式,所有节点始终可以看到所有图像。很疯狂的是,carrierwave默认缓存到./tmp,因为许多多节点配置都会遇到此问题(除非负载均衡器实现会话亲和性)。
以下是我的模型和控制器等内容:https://gist.github.com/3161569 您需要在表单中进行一些自定义工作:
- 无论如何都保存每个上传的文件。 - 在一个隐藏字段中传递上传的文件ID。 - 在保存时查找文件和/或先前上传的ID。 - 进行模型关联。
虽然这种方法不是“魔法”,但它还具有以下出色的附带效果:
- 您只需运行一个后台作业来生成缩略图,而不是每当用户点击“提交”时启动image_magick(这是一个严重的DOS向量,尤其是在内存受限的主机上,如heroku)。 - 您可以在后台按小时迁移图像到S3,上传文件只需具有新的URL(在这种情况下,如果控制器注意到这一点,它需要发出永久重定向)。这真的很好,因为您可以在不更改任何上传或查看代码的情况下将其保留在开发、分段测试等环境中,并随时将某些或全部上传迁移到S3。

如果你不使用Mongoid呢? - stephenmurdoch
@marflar 我相信大多数 SQL 数据库也可以存储二进制数据,例如图片。如果您正在使用 PG,那么这个 SO 答案大型对象接口文档 可能会对您有所帮助。 - Timo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接