简体   繁体   English

Rails Metal(&Rack)是实现高流量Web服务API的好方法吗?

[英]Is Rails Metal (& Rack) a good way to implement a high traffic web service api?

I am working on a very typical web application. 我正在开发一个非常典型的Web应用程序。 The main component of the user experience is a widget that a site owner would install on their front page. 用户体验的主要组成部分是网站所有者将在其首页上安装的小部件。 Every time their front page loads, the widget talks to our server and displays some of the data that returns. 每次加载首页时,小部件都会与我们的服务器通信并显示一些返回的数据。

So there are two components to this web application: 因此,此Web应用程序有两个组件:

  1. the front end UI that the site owner uses to configure their widget 站点所有者用于配置其窗口小部件的前端UI
  2. the back end component that responds to the widget's web api call 响应窗口小部件的web api调用的后端组件

Previously we had all of this running in PHP. 以前我们用PHP运行所有这些。 Now we are experimenting with Rails, which is fantastic for #1 (the front end UI). 现在我们正在尝试使用Rails,这对于#1(前端UI)来说非常棒。 The question is how to do #2, the back serving of widget information, efficiently. 问题是如何高效地执行#2,即小部件信息的后台服务。 Obviously this is much higher load than the front end, since it is called every time the front page loads on one of our clients' websites. 显然,这比前端负载要高得多,因为每次首页加载到我们客户的网站上时都会调用它。

I can see two obvious approaches: 我可以看到两种明显的方法:

A. Parallel Stack : Set up a parallel stack that uses something other than rails (eg our old PHP-based approach) but accesses the same database as the front end A. 并行堆栈 :建立一个使用除rails之外的其他东西的并行堆栈(例如我们旧的基于PHP的方法),但访问与前端相同的数据库

B. Rails Metal : Use Rails Metal/Rack to bypass the Rails routing mechanism, but keep the api call responder within the Rails app B. Rails Metal :使用Rails Metal / Rack绕过Rails路由机制,但是在Rails app中保持api call响应者

My main question: 我的主要问题:

  1. Is Rails/Metal a reasonable approach for something like this? Rails / Metal是一种合理的方法吗?

But also... 但是也...

  1. Will the overhead of loading the Rails environment still be too heavy? 加载Rails环境的开销是否仍然过重?
  2. Is there a way to get even closer to the metal with Rails, bypassing most of the environment? 是否有办法通过Rails更接近金属,绕过大部分环境?
  3. Will Rails/Metal performance approach the perf of a similar task on straight PHP (just looking for ballpark here)? Rails / Metal性能是否会在直接PHP上完成类似的任务(只是在这里寻找球场)?

And... 和...

  1. Is there a 'C' option that would be much better than both A and B? 是否有一个'C'选项比A和B都要好得多? That is, something before going to the lengths of C code compiled to binary and installed as an nginx or apache module? 也就是说,在将C代码编译为二进制并安装为nginx或apache模块之前,有什么东西?

Thanks in advance for any insights. 提前感谢任何见解。

Not really the most elaborate answer but: 不是最精细的答案,但是:

I would not use metal for this, I would use page caching instead. 我不会使用金属,我会使用页面缓存。 That way, the requests will be served by the webserver and no dynamic languages at all. 这样,请求将由网络服务器提供,并且根本不提供动态语言。 When you create a resource clear the corresponding index page. 在创建资源时清除相应的index页面。 A very basic example would be: 一个非常基本的例子是:

class PostsController < ApplicationController
  caches_page :index

  def index
    @posts = Post.all
    respond_to do |format|
      format.html
      format.xml
    end
  end

  def create
    @post = Post.new(params[:post])
    respond_to do |format|
      if @post.save
        expire_page :action => :index
        format.html { redirect_to posts_path }
        format.xml
      else
        format.html { render :action => "new" }
      end
    end
  end
end

For more information read the Caching Guide . 有关更多信息,请阅读“缓存指南”

PHP loads the entire environment on each request. PHP在每个请求上加载整个环境。 In production mode, Rails loads the entire environment once when the server starts up. 在生产模式下,Rails在服务器启动时加载整个环境。 There is certainly a fair amount of Ruby code being executed during normal controller-action invocations. 在正常的控制器动作调用期间肯定会执行相当数量的Ruby代码。 However, in production mode, none of this code is related to loading the environment. 但是,在生产模式下,此代码都与加载环境无关。 And using Rails Metal instead of the usual Rails controller stack removes a number of those layers, yielding a few additional milliseconds of time saved per request. 使用Rails Metal代替通常的Rails控制器堆栈会删除许多这些层,从而为每个请求节省一些额外的毫秒时间。

I would only start pulling functionality down to Rack/Metal if I had determined the exact cause of any performance issue being encountered. 如果我确定遇到任何性能问题的确切原因,我只会开始将功能下拉到Rack / Metal。 Particular in recent versions of Rails (3, in particular) and Ruby, the stack itself is very rarely the bottleneck. 特别是在最新版本的Rails(特别是3)和Ruby中,堆栈本身很少成为瓶颈。 Start measuring, get some real metrics and optimise judiciously. 开始测量,获得一些真实的指标并明智地进行优化。

My rule of thumb: if you don't have metrics, you can't reason intelligently about your performance issue and any possible solution. 我的经验法则:如果您没有指标,则无法智能地了解您的性能问题和任何可能的解决方案。

The issues in my experience are nearly always: the views and the database. 我的经验中的问题几乎总是:视图和数据库。

As Ryan suggests, caching can be incredibly effective ... you can even move you architecture to use a reverse proxy in front of your Rails request stack to provide even more capability. 正如Ryan所说,缓存可以非常有效......您甚至可以移动您的架构,在Rails请求堆栈前使用反向代理来提供更多功能。 A cache like Varnish provides incredibly high-performance. 像Varnish这样的缓存提供了令人难以置信的高性能。 Rails has built-in support for etags and HTTP headers for facilitating a reverse proxy solution. Rails内置了对etags和HTTP头的支持,以便于反向代理解决方案。

The other thing to do is look at the db layer itself. 另一件事是查看db层本身。 The cache can go a long way here, but some optimisation may be useful here too. 缓存在这里可以走很长的路,但是一些优化也可能在这里很有用。 Making sure you use Active Record's :include sensibly is a great step to avoid N+1 query situations, but there is fantastic support in Rails for dropping memcached into the stack with little or no configuration, which can provide excellent performance gains. 确保你使用Active Record:明智地包含是避免N + 1查询情况的一个很好的步骤,但Rails有很好的支持,可以在很少或没有配置的情况下将memcached丢弃到堆栈中,这可以提供出色的性能提升。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM