是否可以直接使用nginx为预编译的资产提供服务?使用Rails动态服务资产的速度大约慢了20倍(在我的virtualbox中,4000 req/sec比200 req/sec)。
我想这可以用nginx.conf中的一些重写规则来完成。然而,问题是,这些文件名包括内容的md5哈希,所以我真的不明白该怎么做。
如果不可能的话,我还不了解Rails3.1资产管道的全部想法。以x20服务器负载为代价减少客户端带宽和页面加载时间?
有什么想法吗?
UPD:所以,我设法以某种方式设置了我的nginx和Rails,当我的应用程序中的所有都以3500-4000请求/秒的速度提供服务时。
首先,我添加了两个虚拟主机,其中一个充当另一个的缓存代理,并发现资产以我想要的速度(4k)提供服务。然后我用memcached连接了我的Rails应用程序(到目前为止没有什么特别的,只是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;
}
}
站点已启用/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;
}
一切都快得像一道血腥的闪电:)谢谢大家。
下面是我从interweb:中收集到的一些额外比特
对于轨道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 ...
}
虽然我没有使用rails的经验,但我猜您使用的是带有proxy_pass指令的nginx+passer。听起来你的"静态资产"有动态url来提供资产,这阻止了你配置nginx通过专门的位置路径直接从nginx提供内容,比如下面的片段:
# static content
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
# access_log off;
expires 15d;
}
如果这是正确的,我给你的建议是尝试使用nginx的proxy_cache指令。这将使您能够控制nginx向乘客"重新生成"先前请求和缓存的响应nginx的频率。这个服务器故障答案应该有助于您演示其用途。使用proxy_cache,您可以缓存任何响应,例如动态生成的图像,甚至只是json/javascript/html内容。
您也可以尝试memcached模块,它将为您提供对缓存的更细粒度的控制。不利的一面是,你必须用代码将你的文件推送到memcached中来填充它。好处是,你可以在某种memcached集群中集中缓存你的内容。
尝试将其添加到您的NGINX配置中:
服务器{。。。位置~*^/资产{过期最大值;add_header缓存控件public;打破}。。。}
好吧,我知道这是一个老问题,但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;
}
也许您应该运行rake assets:precompile
它将把预编译的资产粘贴在/public/assets/