在 EC2 上设置 Rails 2.3.x 应用程序以实现轻松的可扩展性

Max*_*yak 3 scalability ruby-on-rails distributed-filesystems amazon-ec2

我在一台专用机器上运行一个简单的 rails 堆栈。我们正在达到我们的全部容量并且完全没有扩展设置,只有一台机器上的一个应用程序。我做了一些研究,并提出了一个潜在的可扩展堆栈。我不是专业管理员,但我已经就我们应该如何使用 EC2 提出了一些想法。我仍然有点不确定文件系统共享,这是我的主要问题所在。首先,这是我要处理的。

当前堆栈:

  • 导轨 2.3.11
  • PostgreSQL
  • 乘客+nginx
  • 延迟作业
  • 狮身人面像+thinking_sphinx
  • imagemagick(重图像处理)
  • jaxer(将解释)

我们的应用程序的作用:

我们的应用程序使用 ImageMagick 执行大量图像上传和繁重的图像处理。它还与 jaxer 对话以进行冗长的画布到图像的转换。所有这些都在延迟工作中。我们想确保这些东西尤其可以扩展。所以我们谈论的是快速增长的文件存储需求和后台作业中繁重的图像处理。

到目前为止我的决定:

  • 使用 Rubber gem 帮助部署/管理
  • 从 delay_job 移动到 redis/resque,以便更轻松地解耦工作人员(客户端/服务器)、多个队列和 sinatra Web 界面
  • 有像 app、db、web、redis、resque 这样的角色,一开始所有的东西都在一个 ec2 实例上,但很快就把 redis/resque 的东西拆分成一个单独的实例,可能还有更多

问题:

主要的实际问题是:所有文件会发生什么?如果我决定将应用程序角色拆分为多个实例,如何获得共享文件系统访问权限?

此外,很高兴听到关于我的设置的一些想法。

wom*_*ble 9

因此,您所拥有的大部分内容都非常易于扩展。PgSQL 到它自己的机器上,以减轻一堆 CPU/磁盘 IO/内存消耗作为第一步。狮身人面像也进入了它自己的小世界。绝对切换到 resque 以允许您的工作人员轻松水平扩展。

但是文件……是的,文件很难。他们总是很难。而且您的选择非常少。

有些人会推荐集群文件系统路由,要么是神奇的超级集群(GFS2/OCFS2),要么是 GlusterFS 之类的稍微差一点的选项。我已经使用 GFS 运行了很多系统(1000+),而且我永远不会再来一遍。(实际上,它甚至可能无法在 EC2 的网络上运行)。GFS2/OCFS2 是一大堆活动部件,文档不足,过于复杂,并且容易出现令人困惑的故障模式,只会给您带来停机时间的麻烦。它的性能也不值得一提,尤其是在大量写入的环境中——它只是倒下,导致整个集群宕机,并需要 10 到 30 分钟的大师级工作才能让它重新启动并运行。避免它,你的生活就会轻松很多。我从未运行过 GlusterFS,但那是因为我从未对它印象特别深刻。你可以用它做的任何事情,通常都有更好的方法来做。

在我看来,更好的选择是古老的 NFS 服务器。一台机器有一个大(或不是那么大)的 EBS 卷和一个 NFS 守护程序正在运行,每个人都安装它。它有一些问题(它不是真正的 POSIX 文件系统,所以不要这样对待它),但是对于 99% 的用例的简单“那里,我修复了它”操作,这还不错。至少,在您研究更好的解决方案时,它可以是一个权宜之计,那就是……

使用您对应用程序的了解来分层存储。这是我最近采用的方法(扩展 Github),而且效果很好。基本上,不是将文件存储视为文件系统,而是将其视为服务——为应用程序的文件存储使用部分​​提供智能 API,用于执行您需要执行的操作。在您的情况下,您可能只需要能够将图像存储和检索到预先分配的 ID(例如,数据库中“图像”表的 PK)。这不需要整个 POSIX 文件系统,它只需要几个超级优化的 HTTP 方法(POST 需要动态处理,但如果你真的聪明的你可以让 GET 直接从磁盘中作为静态文件)。见鬼,您可能直接将这些图像提供给客户,因此请去掉中间人,并在您使用该服务器时将该服务器设为可公开访问的资产服务器。

工作流程可能类似于:

  • 前端服务器获取图像
    1. POST 到文件服务器
    2. 添加作业以处理图像
    3. (或者,文件服务器的 POST 使其识别出对后处理作业的需求,并自行创建作业)
  • 工人获得图像处理工作
    1. 从文件服务器检索图像
    2. 处理图像
    3. 将处理后的图像 POST 回文件服务器
  • 网页需要在网页中包含图片
    1. 将图像服务器的 URL 写入 HTML
    2. 网络浏览器直接获取图像

您也不一定必须使用 HTTP POST 将图像放到服务器上——例如,Github 使用 Git-over-SSH 与它的文件服务器通信,这对它们来说很好用。但是,关键是要更多地考虑必须完成的工作,并避免不必要地使用稀缺资源(NFS 服务器请求的网络 IO),而是换用一组更受限制的使用选项(“您只能以原子方式请求整个文件!”)适用于您的应用程序。

最后,您将不得不考虑可扩展性因素。但是,如果您使用的是智能传输,那很容易——在与文件服务器通信的每个地方添加确定需要与哪个文件服务器通信所需的(少量)逻辑,并且您基本上获得了无限的可扩展性. 在您的情况下,您可能会意识到您的第一个文件服务器将满载,例如 750,000 个图像。所以你的规则是“用主机名与文件服务器交谈fs#{image_id / 750_000}”,这并不难在任何地方编码。

我过去常常在这部分工作中玩得很开心......