35 votes

Servir des actifs précompilés avec nginx

Est-il possible de servir précompilés actifs avec nginx directement? Portion de l'actif de manière dynamique avec des Rails, c'est comme 20 fois plus lent (4000 req/sec vs 200 req/sec dans ma virtualbox).

Je suppose que cela peut être fait avec une certaine règle de réécriture dans nginx.conf. Le problème est, cependant, que ces fichiers comprennent du hachage md5 du contenu, donc je ne comprends pas vraiment ce qui peut être fait avec ce.

Si ce n'est pas possible je n'ai pas l'idée de Rails 3.1 actif pipelines. Réduction de la bande passante des clients et des temps de chargement de page, au prix de x20 charge du serveur?

Des idées?

UPD: Alors, j'ai réussi à configurer mon nginx et des Rails d'un chemin, quand tout dans mon application est servi à la vitesse d'environ 3500 à 4000 requêtes/sec.

Tout d'abord, j'ai ajouté deux hôtes virtuels, avec une servant de proxy cache à l'autre et a découvert que les actifs sont servis à la vitesse que je voulais (4k). Puis je l'ai connecté mon application Rails avec memcached (rien de spécial jusqu'à présent, une seule ligne dans l'application.rb: ActionController::Base.cache_store = :mem_cache_store, "localhost")

Ensuite, j'ai ajouté des choses comme expires_in 1.hour, :public => true if !signed_in?; de mes contrôleurs à défaut de changement politique de mise en cache des Rails de contenu et a obtenu gain de vitesse autour de 500 requêtes par seconde pour mes pages dynamiques (avant que c'était quelque chose près de 200, et il était d'environ 50 avant que j'aie commencé tout cela).

Maintenant, quand mon nginx fichiers de configuration ressembler à ceci:

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;

    }

Tout est rapide comme un putain de foudre :) Merci, les gars.

35voto

Ben W Points 2272

Après d'en haut avec quelques bits supplémentaires, j'ai glané de l'interweb:

Pour 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;
}
 

Pour l'utilisation de Rails 3.0

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

12voto

pcting Points 683

Bien que je n'ai pas d'expérience de travail avec des rails, ma conjecture est que vous êtes en utilisant nginx + passager avec le proxy_pass directive. Il semble que votre "statique actifs" ont des url dynamiques pour servir les actifs, ce qui vous empêche de configurer nginx pour servir le contenu directement à partir de nginx spécialisés emplacement chemins comme l'extrait de suivre:

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

Si cela est correct, mon conseil pour vous est d'essayer en utilisant nginx est proxy_cache directive. Cela vous permettra de contrôler la façon dont souvent nginx va aux passagers de se "régénérer" la réponse de nginx enregistré précédemment demandé et mis en cache. Ce serveur faute de réponse devrait vous aider doit démontrer l'utilisation. Avec proxy_cache, vous pouvez mettre en cache toutes les interventions, notamment généré dynamiquement des images ou même juste en json/javascript/html contenu.

Vous pouvez également essayer les memcached module, qui vous donnera un contrôle plus fin sur la mise en cache. L'inconvénient de ceci est que vous avez fait pousser vos fichiers dans memcache avec un code pour le remplir. L'avantage est, vous pouvez centraliser le cache de votre contenu dans une sorte de cluster memcached.

6voto

bodacious Points 2322

Essayez d'ajouter ceci à votre configuration NGINX:

serveur {

  ...

  emplacement ~ * ^ / actifs {
    expire max;
    add_header Cache-Control public;
    Pause;
  }

  ...

}

2voto

Jim Lim Points 4981

Eh bien, je sais que c'est une vieille question, mais le passager autonome le fait comme suit:

     # 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;
    }
 

1voto

vous devriez peut-être exécuter rake assets:precompile Il collera les actifs précompilés sous / public / assets /

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X