• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Nginx: Accelerate Rails, HTTP Tricks
 

Nginx: Accelerate Rails, HTTP Tricks

on

  • 19,773 views

Adam Wiggins' Railsconf 2008 session talk.

Adam Wiggins' Railsconf 2008 session talk.

Statistics

Views

Total Views
19,773
Views on SlideShare
19,705
Embed Views
68

Actions

Likes
34
Downloads
320
Comments
0

3 Embeds 68

http://www.slideshare.net 64
http://aaron.local.host:3000 2
http://www.slideee.com 2

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Nginx: Accelerate Rails, HTTP Tricks Nginx: Accelerate Rails, HTTP Tricks Presentation Transcript

    • Nginx: Accelerate Rails, HTTP Tricks Adam Wiggins Railsconf 2008
    • Nginx is a webserver
    • Which means: Nginx replaces Apache
    • Nginx replaces Apache ‣Faster ‣Smaller memory footprint ‣More stable under load ‣More secure
    • But more importantly:
    • But more importantly: Nginx is a better fit for Rails
    • Apache is the right tool: ‣mod_php ‣owning your own server hardware
    • Apache is the right tool: ‣mod_php ‣owning your own server hardware The era now coming to a close.
    • The era now upon us: ‣Rails ‣cloud computing
    • The era now upon us: ‣Rails ‣cloud computing Which both work best with proxying.
    • Proxying is Nginx’s primary mechanism for serving dynamic content
    • “One thing”
    • Embrace the constraint of keeping application VMs out of the front-end webserver
    • Ok cool.
    • Ok cool. Wait, there’s something funny going on here...
    • Nginx is not a webserver?
    • Nginx is an HTTP router
    • Enough abstraction; let’s see some code
    • Proxy balancing example upstream myapp_mongrels { 127.0.0.1:3000; 127.0.0.1:3001; } location / { proxy_pass http://myapp_mongrels; }
    • Memcached in front location / { set $memcached_key $uri; memcached_pass 127.0.0.1:11211; error_page 404 502 = @myapp; } location @myapp { internal; proxy_pass http://myapp_mongrels; }
    • Memcached method filter location / { if ($request_method = GET) { set $memcached_key $uri; memcached_pass 127.0.0.1:11211; error_page 404 502 = @myapp; break; } proxy_pass http://myapp_mongrels; }
    • Filtering
    • Filtering is reaching in and tinkering with requests and responses
    • Separate concerns:
    • Separate concerns: ‣Filters in your app for business logic
    • Separate concerns: ‣Filters in your app for business logic ‣Filters in your http router for server infrastructure
    • Separate concerns: ‣Filters in your app for business logic ‣Filters in your http router for server infrastructure ‣Filters in either for application infrastructure
    • Separate concerns: ‣Filters in your app for business logic ‣Filters in your http router for server infrastructure ‣Filters in either for application infrastructure
    • Time to get hardcore: Custom Nginx modules
    • http://emiller.info/nginx-modules-guide.html
    • The problem: Granular user access control
    • The Rails solution: before_filter
    • The Rails solution: before_filter before_filter :authorize def authorize @user = User.find(session[:user_id]) @resource = request.env['REQUEST_URI'] redirect_to '/login' unless @user redirect_to '/access_denied' unless @user.can_access(@resource) end
    • Can we do this without touching the Rails app’s code?
    • The Nginx solution: input filter module
    • The Nginx solution: input filter module ngx_heroku_gate
    • before_filter :authorize
    • before_filter :authorize static ngx_int_t ngx_heroku_gate_init(ngx_conf_t *cf) { phase = cmcf->phases[NGX_HTTP_ACCESS_PHASE]; h = ngx_array_push(&phase.handlers); *h = ngx_heroku_gate_handler; }
    • def authorize @user = User.find(session[:user_id]) @resource = request.env['REQUEST_URI']
    • def authorize @user = User.find(session[:user_id]) @resource = request.env['REQUEST_URI'] static ngx_int_t ngx_heroku_gate_handler (ngx_http_request_t *req) { user = get_logged_in_user( req->headers_in.cookies); app_name = get_app_name( req->headers_in.host->value.data);
    • redirect_to '/login' unless @user
    • redirect_to '/login' unless @user if (!user) { redirect_to(req, '/login'); return NGX_HTTP_MOVED_TEMPORARILY; }
    • redirect_to '/access_denied' unless @user.can_access(@resource)
    • redirect_to '/access_denied' unless @user.can_access(@resource) if (!user_can_access(user, app)) { redirect_to(req, '/access_denied'); return NGX_HTTP_MOVED_TEMPORARILY; } else { write_heroku_user_header(req, user); return NGX_OK; }
    • #define X_HEROKU_USER quot;X-Heroku-Userquot; static void write_heroku_user_header (ngx_http_request_t *r, u_char *user) { h = ngx_list_push( &r->headers_in.headers); h->hash = 1; h->key.len = sizeof(X_HEROKU_USER) - 1; h->key.data = (u_char *) X_HEROKU_USER; h->value.len = strlen((char *)user); h->value.data = user; }
    • The Rails solution: before_filter before_filter :authorize def authorize @user = User.find(session[:user_id]) @resource = request.env['REQUEST_URI'] redirect_to '/login' unless @user redirect_to '/access_denied' unless @user.can_access(@resource) end
    • The Nginx solution: input filter static ngx_int_t ngx_heroku_gate_handler(ngx_http_request_t *req) { user = get_logged_in_user(req->headers_in.cookies); app_name = get_app_name(req->headers_in.host->value.data); if (!user) { redirect_to(req, '/login'); return NGX_HTTP_MOVED_TEMPORARILY; } if (!user_can_access(user, app)) { redirect_to(req, '/access_denied'); return NGX_HTTP_MOVED_TEMPORARILY; } else { write_heroku_user_header(req, user); return NGX_OK; } }
    • A word on performance
    • Closing thoughts / the future
    • HTTP is the enabling protocol for the era of cloud computing
    • http://nginx.ru http://emiller.info/nginx-modules-guide.html http://igvita.com/2008/02/11/nginx-and-memcached Adam Wiggins http://adam.blog.heroku.com