使用nginx提供预编译资产

时间:2011-06-19 12:12:16

标签: ruby-on-rails ruby-on-rails-3 nginx

是否可以直接使用nginx提供预编译资产?使用Rails动态提供资源的速度要慢20倍(4000 req / sec对比我的virtualbox中的200 req / sec)。

我想可以在nginx.conf中使用一些重写规则来完成。但问题是,这些文件名包含内容的md5哈希,所以我真的不明白可以用这个做什么。

如果不可能,我不会使用Rails 3.1资产管道获得全部想法。以x20服务器负载为代价减少客户端带宽和页面加载时间?

有什么想法吗?

UPD:所以,当我的应用程序中的一切以~3500-4000请求/秒的速度提供时,我设法以某种方式设置我的nginx和Rails。

首先,我添加了两个虚拟主机,其中一个作为另一个的缓存代理,发现资产以我想要的速度提供(4k)。然后我将我的Rails应用程序连接到memcached(到目前为止没有什么特别的,只是application.rb中的一行:ActionController::Base.cache_store = :mem_cache_store, "localhost"

然后我将expires_in 1.hour, :public => true if !signed_in?;之类的内容添加到我的控制器中以更改Rails内容的默认缓存策略,并为我的动态页面获得大约500个请求/每秒的速度提升(之前它接近200,并且它在我开始这一切之前是~50。

现在,当我的nginx配置文件看起来像这样:

nginx.conf:

...
proxy_cache_path  /tmp/blog keys_zone=one:8m max_size=1000m inactive=600m;
proxy_temp_path /tmp;
gzip  off;
include /opt/nginx/conf/sites-enabled/*;

/博客网站启用 - :

server {
        listen   8080;
        server_name  blindsight;

        root   /home/mike/rails/blog/public;
        rails_env production;

        # serve static content directly
        location ~* \.(ico|jpg|gif|png|swf|html)$ {
          if (-f $request_filename) {
            expires max;
            break;
          }
        }

        passenger_enabled on;

        location ~ /\.ht {
          deny  all;
        }
}

启用位点-/主:

server {

    listen   80;
    server_name  blindsight;

    location /authorize
    {
       proxy_pass_header Cookie;
       proxy_pass_header Set-Cookie;
       proxy_pass http://127.0.0.1:8080;
    }

    location /admin
    {
       proxy_pass_header Set-Cookie;
       proxy_pass_header Cookie;
       proxy_pass http://127.0.0.1:8080;
    }

    location / {
    root /home/mike/rails/blog/public;

        # All POST requests go directly
        if ($request_method = POST) {
          proxy_pass http://127.0.0.1:8080;
          break;
        }

    proxy_redirect off;
    proxy_pass_header Cookie;
    proxy_ignore_headers Set-Cookie;
    proxy_hide_header Set-Cookie;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_cache one;
    proxy_cache_key blog$request_uri;
    proxy_cache_valid 200 302  5s;
    proxy_cache_valid 404      1m;
    proxy_pass http://127.0.0.1:8080;

    }

一切都像血腥闪电一样快:) 谢谢你们,伙计们。

5 个答案:

答案 0 :(得分:34)

从上面开始,我从interweb收集了一些额外的位:

对于Rails 3.1:

location ~* ^/assets/ {
    # Per RFC2616 - 1 year maximum expiry
    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
    expires 1y;
    add_header Cache-Control public;

    # Some browsers still send conditional-GET requests if there's a
    # Last-Modified header or an ETag header even if they haven't
    # reached the expiry date sent in the Expires header.
    add_header Last-Modified "";
    add_header ETag "";
    break;
}

对于Rails 3.0,请使用

location ~* ^/(images|javascripts|stylesheets)/ {
    ... copy block from above ...
}

答案 1 :(得分:11)

虽然我没有使用rails的经验,但我猜你是在使用带有proxy_pass指令的nginx + passenger。听起来你的“静态资产”有动态网址来提供资产,这会阻止你配置nginx直接从nginx通过专门的位置路径提供内容,如以下代码段:

#  static content
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
  # access_log        off;
  expires           15d;
}

如果这是正确的,我建议您尝试使用nginx的proxy_cache指令。这将让你控制nginx去乘客“重新生成”以前保存的请求和缓存的响应nginx的频率。 This server fault answer应该帮助您展示使用方法。使用proxy_cache,您可以缓存任何响应,例如动态生成的图像,甚至只是json / javascript / html内容。

您还可以尝试memcached模块,它将为您提供更精细的缓存控制。这方面的缺点是您必须实际将文件推送到内存中,并使用代码填充它。好处是,您可以在某种memcached集群中集中缓存您的内容。

答案 2 :(得分:5)

尝试将此添加到您的NGINX配置中:

server {

  ...

  location ~* ^/assets {
    expires max;
    add_header Cache-Control public;
    break;
  }

  ...

}

答案 3 :(得分:2)

嗯,我知道这是一个老问题,但Passenger独立版如下:

    # Rails asset pipeline support.
    location ~ ^/assets/ {
        error_page 490 = @static_asset;
        error_page 491 = @dynamic_request;
        recursive_error_pages on;

        if (-f $request_filename) {
            return 490;
        }
        if (!-f $request_filename) {
            return 491;
        }
    }
    location @static_asset {
        gzip_static on;
        expires max;
        add_header Cache-Control public;
        add_header ETag "";
    }
    location @dynamic_request {
        passenger_enabled on;
    }

答案 4 :(得分:1)

也许你应该运行rake assets:precompile 它会将预编译资产粘贴在/ public / assets /