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

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

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

当前堆栈:

  • rails 2.3.11
  • PostgreSQL
  • 乘客+nginx
  • 延迟作业
  • sphinx + thinking_sphinx
  • imagemagick(重型图像处理)
  • jaxer(将会解释)

我们的应用程序的作用:

我们的应用程序使用 ImageMagick 进行大量图像上传和繁重的图像处理。它还会与 jaxer 通信,以进行冗长的画布到图像转换。所有这些都是延迟作业。我们希望确保这些工作能够扩展。因此,我们谈论的是快速增长的文件存储需求和后台作业中的繁重图像处理。

我目前做出的决定:

  • 使用 rubber gem 帮助部署/管理
  • 从 delayed_job 移至 redis/resque,以便更轻松地解耦工作者(客户端/服务器)、多个队列和 sinatra web 界面
  • 具有 app、db、web、redis、resque 等角色,最初所有角色都在一个 ec2 实例上,但很快将 redis/resque 内容拆分为单独的实例,并且可能会有更多此类实例

问题:

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

此外,如果能听到大家对我的设置的一些总体看法,那就太好了。

答案1

因此,您拥有的大部分内容都很容易扩展。第一步是将 PgSQL 放到自己的机器上,以减轻 CPU/磁盘 IO/内存消耗。Sphinx 也进入了自己的小世界。一定要切换到 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. 将其发布到文件服务器
    2. 添加作业以处理图像
    3. (或者,文件服务器的 POST 使其认识到需要进行后处理作业,并且它自己创建该作业)
  • 工人获得图像处理工作
    1. 从文件服务器检索图像
    2. 处理图像
    3. 将处理后的图像发送回文件服务器
  • 网页需要在网页中包含图片
    1. 将图片服务器的 URL 写入 HTML
    2. 网络浏览器直接获取图像

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

最后,您必须考虑可扩展性因素。但是,如果您使用的是智能传输,那么这很容易 - 在每个与文件服务器通信的地方添加(少量)确定需要与哪个文件服务器通信所需的逻辑,您基本上就拥有了无限的可扩展性。在您的情形下,您可能会意识到您的第一个文件服务器在 750,000 张图像时就会满负荷。因此,您的规则是“与具有主机名的文件服务器通信fs#{image_id / 750_000}”,这在任何地方进行编码并不难。

我以前总是对我的工作的这部分感到很有趣...

相关内容