Обслуживание предварительно скомпилированных активов с помощью nginx
Можно ли напрямую использовать предварительно скомпилированные активы с nginx? Динамическое обслуживание ресурсов с помощью Rails в 20 раз медленнее (4000 req/sec против 200 req/sec в моем виртуальном боксе).
Я думаю, это можно сделать с помощью некоторого правила перезаписи в nginx.conf. Однако проблема заключается в том, что эти имена файлов включают хеш-содержимое md5, поэтому я не понимаю, что с этим можно сделать.
Если это невозможно, я не понимаю всю идею с конвейерами Rails 3.1. Сокращение клиентской пропускной способности и времени загрузки страницы за счет загрузки сервера x20?
Любые идеи?
UPD: Итак, мне удалось настроить мои nginx и Rails в некотором смысле, когда все в моем приложении подано со скоростью ~ 3500-4000 запросов/сек.
Прежде всего, я добавил два виртуальных хоста, один из которых служил в качестве кэширующего прокси-сервера другому, и обнаружил, что активы обслуживаются с той скоростью, которую я хотел (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;
}
Все быстро, как кровавая молния:)
Спасибо, ребята.
Ответы
Ответ 1
Хотя у меня нет опыта работы с рельсами, я предполагаю, что вы используете nginx + пассажир с директивой proxy_pass. Похоже, ваши "статические активы" имеют динамические 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, который даст вам более тонкий контроль над кешированием. Нижняя сторона этого заключается в том, что вы должны фактически нажимать свои файлы в memcache с кодом, чтобы заполнить его. Потенциал заключается в том, что вы можете централизовать кеширование своего содержимого в каком-то кластере memcached.
Ответ 2
Следуя сверху с некоторыми дополнительными битами, которые я почерпнул из 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 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 ...
}
Ответ 3
Попробуйте добавить это в конфигурацию NGINX:
server {
...
location ~* ^/assets {
expires max;
add_header Cache-Control public;
break;
}
...
}
Ответ 4
Ну, я знаю, что это старый вопрос, но автономный Пассажир делает это следующим образом:
# 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;
}
Ответ 5
возможно, вам следует запустить rake assets:precompile
Он будет хранить прекомпилированные активы под/public/assets/