Ruby-on-rails 使用 nginx 提供预编译资产
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6402278/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Serving precompiled assets with nginx
提问by Jake Jones
Is it possible to serve precompiled assets with nginx directly? Serving assets dynamically with Rails is like 20 times slower (4000 req/sec vs 200 req/sec in my virtualbox).
是否可以直接使用 nginx 提供预编译资产?使用 Rails 动态提供资源的速度要慢 20 倍(4000 req/sec vs 200 req/sec 在我的虚拟机中)。
I guess it can be done with some rewrite rule in nginx.conf. The problem is, however, that these filenames include md5 hash of the content, so I don't really understand what can be done with this.
我想这可以通过 nginx.conf 中的一些重写规则来完成。然而,问题是这些文件名包含内容的 md5 哈希,所以我真的不明白可以用它做什么。
If its not possible I don't get the whole idea with Rails 3.1 asset pipelines. Reducing client bandwidth and page load time at the cost of x20 server load?
如果不可能的话,我不明白 Rails 3.1 资产管道的全部想法。以 x20 服务器负载为代价减少客户端带宽和页面加载时间?
Any ideas?
有任何想法吗?
UPD: So, I managed to setup my nginx and Rails in a way, when everythingin my application is served at the speed of ~3500-4000 requests/sec.
UPD:所以,当我的应用程序中的所有内容都以大约 3500-4000 个请求/秒的速度提供服务时,我设法以某种方式设置了我的 nginx 和 Rails 。
First of all I added two virtual hosts, with one serving as a caching proxy to another and discovered that assets are served at the speed I wanted (4k). Then I connected my Rails application with memcached (nothing special so far, just one line in application.rb: ActionController::Base.cache_store = :mem_cache_store, "localhost")
首先,我添加了两个虚拟主机,一个用作另一个的缓存代理,并发现资产以我想要的速度(4k)提供服务。然后,我连我的Rails应用程序使用memcached的(没有什么特别的,到目前为止,只有一行在application.rb中:ActionController::Base.cache_store = :mem_cache_store, "localhost")
Then I added things like expires_in 1.hour, :public => true if !signed_in?;to my controllers to change default caching policy of Rails content and got speed boost around 500 requests/per second for my dynamic pages (before that it was something close to 200, and it was ~50 before I ever started this all).
然后我expires_in 1.hour, :public => true if !signed_in?;在我的控制器中添加了一些东西来更改 Rails 内容的默认缓存策略,并为我的动态页面提高了大约 500 个请求/每秒的速度(在此之前它接近 200,在我开始之前它是大约 50 个)全部)。
Now, when my nginx config files look like this:
现在,当我的 nginx 配置文件如下所示:
nginx.conf:
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/*;
sites-enabled/blog:
启用网站/博客:
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;
}
}
sites-enabled/main:
站点启用/主要:
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;
}
Everything is fast like a bloody lightning :) Thank you, guys.
一切都像血腥的闪电一样快:) 谢谢你们。
采纳答案by pcting
Although I don't have experience working with rails, my guess is you're using nginx + passenger with the proxy_pass directive. It sounds like your "static assets" have dynamic urls to serve the assets, which prevents you from configuring nginx to serve the content from directly from nginx through specialized location paths like the follow snippet:
虽然我没有使用 rails 的经验,但我猜你正在使用 nginx +passenger 和 proxy_pass 指令。听起来您的“静态资产”具有动态 url 来提供资产,这会阻止您配置 nginx 以通过专门的位置路径直接从 nginx 提供内容,如以下代码段:
# static content
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
# access_log off;
expires 15d;
}
If this is correct, my advice to you is to try using nginx's proxy_cachedirective. This will let you control how often nginx goes to passenger to "regenerate" the response nginx saved previously requested and cached. This server fault answershould help you should demonstrate the use. With proxy_cache, you can cache any response such as dynamically generated images or even just json/javascript/html content.
如果这是正确的,我给您的建议是尝试使用 nginx 的proxy_cache指令。这将让您控制 nginx 前往乘客的频率,以“重新生成” nginx 保存的先前请求和缓存的响应。这个服务器故障答案应该可以帮助您演示使用。使用 proxy_cache,您可以缓存任何响应,例如动态生成的图像,甚至只是 json/javascript/html 内容。
You could also try the memcachedmodule, which will give you a more fine-grained control over caching. The down side to this is you have to actually push your files into memcache with code to populate it. The upside is, you can centrally cache your content in some sort of memcached cluster.
您还可以尝试使用memcached模块,它可以让您更精细地控制缓存。不利的一面是您必须实际将文件推送到带有代码的内存缓存中以填充它。好处是,您可以在某种 memcached 集群中集中缓存您的内容。
回答by Ben Walding
Following on from above with some extra bits I gleaned from the interweb:
从上面开始,我从互联网上收集了一些额外的信息:
For Rails 3.1:
对于 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;
}
For Rails 3.0 use
对于 Rails 3.0 使用
location ~* ^/(images|javascripts|stylesheets)/ {
... copy block from above ...
}
回答by bodacious
Try adding this to your NGINX config:
尝试将其添加到您的 NGINX 配置中:
server {
...
location ~* ^/assets {
expires max;
add_header Cache-Control public;
break;
}
...
}
回答by James Lim
Well, I know this is an old question, but the Passenger standalone does it as follows:
好吧,我知道这是一个老问题,但乘客独立的做法如下:
# 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;
}
回答by Tom van Leeuwen
maybe you should run rake assets:precompileIt will stick precompiled assets under /public/assets/
也许你应该运行rake assets:precompile它会将预编译的资产粘贴在 /public/assets/ 下

