2008年12月17日,星期三

隆重推出 Rails Metal

作者:David

Rails Edge 很久以前就采用了 Rack,我们一直在探索更好的暴露它的方法。我们做的第一件事就是让在 Rails 请求之前非常容易地连接任何 Rack 中间件。在您的 config/environment.rb 文件中,您可以这样做:

config.middlewares.use(Rack::Cache, :verbose => true)

这将使您的应用程序使用 Ryan Tomayko 出色的 Rack::Cache 中间件 来实现更好的 HTTP 缓存。还有许多其他很棒的通用、可重用的 Rack 中间件。不妨去逛逛。

但 Rack 在另一种用例中也很有用。如果您有一个 Rails 应用程序,其中包含需要非常非常快的服务终结点。快到 Rails 路由和 Action Controller 路径的几毫秒往返都显得太多了。

对于这种情况,我们构建了一个围绕通用 Rack 中间件的轻量级包装器,并将其命名为“Metal”,在层次结构中占有一席之地。Rails Metal 适用于 Campfire 轮询服务之类的应用,该服务每秒处理数百个请求,需要非常快速,同时又非常简单(2 个数据库调用并返回一个字符串)。该服务目前是用 C 编写的,但我们将考虑将其转换为 Rails Metal。

Rails Metal 是 Rack 中间件的子集
将 Rails Metal 视为一套旨在满足特定应用程序端点的中间件,这些端点需要额外的速度(“直接写入底层”,因此得名)。由于最近采用了 Rack 会话,这些 Metal 片段甚至可以访问与 Rails 相同的会话。您可以将它们作为 Rails 进程的一部分运行,也可以通过 rackup 将它们作为独立服务运行。

我们甚至为 Metal 提供了一个生成器,默认情况下它会创建一个类似以下的存根:

class Poller def self.call(env) if env[“PATH_INFO”] =~ /^\/poller/ [200, {"Content-Type" => “text/html”}, “Hello, World!”] else [404, {"Content-Type" => “text/html”}, “Not Found”] end end end

正如您所见,这只是捕获对 /poller 的请求并返回“Hello, World!”(如果请求不是针对 /poller,它会交给 Rails 路由处理——这就是 404 返回的作用)。它的速度几乎与 Rack 在技术上可能达到的最快速度一样快(引用一个无用的指标,说明 Rails 现在拥有最快、最有意义的“hello world”统计数据!!)。

请注意,这是一个相当专业的工具。虽然您可以用 Metal 编写整个 Rails 应用程序,但在大多数情况下,这是一个糟糕的主意。绝大多数应用程序的速度都足够快,以至于已经高度优化的 Rails 路由和 Action Controller 执行路径的开销不会有丝毫影响(通过 torrent 下载 Michael Koziarski 关于 Rails 性能的演讲 以获取更多信息)。

此外,如果您要编写像 Rack::Cache 这样的通用过滤器,Metal 也不合适。您应该只创建可以跨所有 Rack 应用程序共享的常规中间件。

但是,对于那些只需要尽可能快速度的特殊情况,Metal 正是您所需要的。它使您能够在一个包中拥有两全其美。当速度至关重要时,Rack 应用程序的开销最低,而在速度不那么重要时,则拥有功能齐全的 Action Controller 的优势。

希望您喜欢这个。Josh Peek 付出了不懈的努力,将 Rails 迁移到 Rack,这只是他努力的最新成果。非常感谢,Josh!

更新: Jesse Newland 还撰写了一篇关于 Metal 的精彩介绍。其中包含基准测试和更多示例!

更新 2:已更改代码示例以匹配最新样式