缩放 Rails 活动存储
Scaling Rails Active Storage
如今Active Storage在Rails的基础上成为一些项目文件存储的首选解决方案。因此,它作为上传内置工具运行良好,但如果不使用云提供商,您将如何解决扩展问题?
我的storage.yaml内容:
local:
service: Disk
root: <%= Rails.root.join("storage") %>
假设我有 rails1 和 rails2 Docker 容器,其中包含完全相同的 Rails 项目和内容。
负载均衡器使用循环法将请求路由到两个容器。
1) 你知道 Rails 是否有内置的东西来解决本地存储的高可用性问题吗?
2) 是否可以保证用户一次只上传到一个Rails实例?然后可以单向复制文件。
3) 如果我设法确保 storage
目录是双向复制的,除了 storage
数据之外,Active Storage 是否还有任何其他位置可以写入内容?缓存,数据库等。所以至少我知道我只需要关注 storage
dir.
4) 您是否建议创建一个单独的文件存储解决方案,例如 NFS(类似于云的东西)并挂载到两个容器上进行读写?考虑到简单性,此解决方案看起来如何?
任何其他解决方案都将很高兴知道。
非常感谢
1, 2) 我实际上在应用程序级别解决了这个问题。 ActiveStorage 有一个很好的机制来获取文件位置、url、大小和其他参数。因此,当您知道其他实例是否缺少某些内容时,它可以从另一个实例下载,或者当某个实例上传了某些内容时,它可以通知其他人获取文件。不是必须的,但我使用了 flock 和 thread 来确保操作是唯一的并且在后台完成。我也考虑过"mirror",但是官方文档说这是为了备份。此外,我想避免使用 NFS 等外部存储,因为您还需要考虑它的可用性。
开始探索这个的一些例子:
# Take first image
image = Ad.find(3770).images.first
# Get key
image_key = Ad.find(3770).images.first.key
# Get location on disk
image_location_on_disk = ActiveStorage::Blob.service.path_for(image_key)
# Include URL helper
include Rails.application.routes.url_helpers
# Get URL
url = Rails.application.routes.url_helpers.rails_blob_path(image, only_path: true)
# Get size
size = File.size?(image_location_on_disk)
# Check if file exists
size = File.exist?(image_location_on_disk)
3) 不。它只写入 storage
目录,这些文件可以复制到另一个 Rails 实例,所以这足以让另一个 Rails 实例工作。
4) 我没有亲自测试过,但使用 NFS 可能会解决问题。另一方面,您应该确保 NFS 服务器可用。 ActiveStorage 创建唯一的文件,因此如果两个实例写入同一存储,则冲突似乎是不可能的。
如今Active Storage在Rails的基础上成为一些项目文件存储的首选解决方案。因此,它作为上传内置工具运行良好,但如果不使用云提供商,您将如何解决扩展问题?
我的storage.yaml内容:
local:
service: Disk
root: <%= Rails.root.join("storage") %>
假设我有 rails1 和 rails2 Docker 容器,其中包含完全相同的 Rails 项目和内容。
负载均衡器使用循环法将请求路由到两个容器。
1) 你知道 Rails 是否有内置的东西来解决本地存储的高可用性问题吗?
2) 是否可以保证用户一次只上传到一个Rails实例?然后可以单向复制文件。
3) 如果我设法确保 storage
目录是双向复制的,除了 storage
数据之外,Active Storage 是否还有任何其他位置可以写入内容?缓存,数据库等。所以至少我知道我只需要关注 storage
dir.
4) 您是否建议创建一个单独的文件存储解决方案,例如 NFS(类似于云的东西)并挂载到两个容器上进行读写?考虑到简单性,此解决方案看起来如何?
任何其他解决方案都将很高兴知道。
非常感谢
1, 2) 我实际上在应用程序级别解决了这个问题。 ActiveStorage 有一个很好的机制来获取文件位置、url、大小和其他参数。因此,当您知道其他实例是否缺少某些内容时,它可以从另一个实例下载,或者当某个实例上传了某些内容时,它可以通知其他人获取文件。不是必须的,但我使用了 flock 和 thread 来确保操作是唯一的并且在后台完成。我也考虑过"mirror",但是官方文档说这是为了备份。此外,我想避免使用 NFS 等外部存储,因为您还需要考虑它的可用性。
开始探索这个的一些例子:
# Take first image
image = Ad.find(3770).images.first
# Get key
image_key = Ad.find(3770).images.first.key
# Get location on disk
image_location_on_disk = ActiveStorage::Blob.service.path_for(image_key)
# Include URL helper
include Rails.application.routes.url_helpers
# Get URL
url = Rails.application.routes.url_helpers.rails_blob_path(image, only_path: true)
# Get size
size = File.size?(image_location_on_disk)
# Check if file exists
size = File.exist?(image_location_on_disk)
3) 不。它只写入 storage
目录,这些文件可以复制到另一个 Rails 实例,所以这足以让另一个 Rails 实例工作。
4) 我没有亲自测试过,但使用 NFS 可能会解决问题。另一方面,您应该确保 NFS 服务器可用。 ActiveStorage 创建唯一的文件,因此如果两个实例写入同一存储,则冲突似乎是不可能的。