Nginx: Accelerate Rails, HTTP Tricks

57
Nginx: Accelerate Rails, HTTP Tricks Adam Wiggins Railsconf 2008

description

Adam Wiggins' Railsconf 2008 session talk.

Transcript of Nginx: Accelerate Rails, HTTP Tricks

Page 1: Nginx: Accelerate Rails, HTTP Tricks

Nginx:Accelerate Rails,HTTP Tricks

Adam WigginsRailsconf 2008

Page 2: Nginx: Accelerate Rails, HTTP Tricks

Nginx is a webserver

Page 3: Nginx: Accelerate Rails, HTTP Tricks

Nginx replaces ApacheWhich means:

Page 4: Nginx: Accelerate Rails, HTTP Tricks

‣Faster‣Smaller memory footprint‣More stable under load‣More secure

Nginx replaces Apache

Page 5: Nginx: Accelerate Rails, HTTP Tricks

But more importantly:

Page 6: Nginx: Accelerate Rails, HTTP Tricks

But more importantly:

Nginx is a better fitfor Rails

Page 7: Nginx: Accelerate Rails, HTTP Tricks

Apache is the right tool:

‣mod_php‣owning your own server hardware

Page 8: Nginx: Accelerate Rails, HTTP Tricks

Apache is the right tool:

‣mod_php‣owning your own server hardware

The era now coming to a close.

Page 9: Nginx: Accelerate Rails, HTTP Tricks

‣Rails‣cloud computing

The era now upon us:

Page 10: Nginx: Accelerate Rails, HTTP Tricks

Which both work best with proxying.

‣Rails‣cloud computing

The era now upon us:

Page 11: Nginx: Accelerate Rails, HTTP Tricks

Proxying is Nginx’sprimary mechanism forserving dynamic content

Page 12: Nginx: Accelerate Rails, HTTP Tricks

“One thing”

Page 13: Nginx: Accelerate Rails, HTTP Tricks

Embrace the constraintof keeping applicationVMs out of the front-endwebserver

Page 14: Nginx: Accelerate Rails, HTTP Tricks

Ok cool.

Page 15: Nginx: Accelerate Rails, HTTP Tricks

Wait, there’s something funnygoing on here...

Ok cool.

Page 16: Nginx: Accelerate Rails, HTTP Tricks

Nginx is not a webserver?

Page 17: Nginx: Accelerate Rails, HTTP Tricks

Nginx is an HTTP router

Page 18: Nginx: Accelerate Rails, HTTP Tricks
Page 19: Nginx: Accelerate Rails, HTTP Tricks
Page 20: Nginx: Accelerate Rails, HTTP Tricks
Page 21: Nginx: Accelerate Rails, HTTP Tricks
Page 22: Nginx: Accelerate Rails, HTTP Tricks
Page 23: Nginx: Accelerate Rails, HTTP Tricks

Enough abstraction;let’s see some code

Page 24: Nginx: Accelerate Rails, HTTP Tricks

Proxy balancing example

upstream myapp_mongrels { 127.0.0.1:3000; 127.0.0.1:3001;}

location / { proxy_pass http://myapp_mongrels;}

Page 25: Nginx: Accelerate Rails, HTTP Tricks

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

Page 26: Nginx: Accelerate Rails, HTTP Tricks

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

Page 27: Nginx: Accelerate Rails, HTTP Tricks

Filtering

Page 28: Nginx: Accelerate Rails, HTTP Tricks

Filtering is reaching inand tinkering withrequests and responses

Page 29: Nginx: Accelerate Rails, HTTP Tricks
Page 30: Nginx: Accelerate Rails, HTTP Tricks

Separate concerns:

Page 31: Nginx: Accelerate Rails, HTTP Tricks

Separate concerns:

‣Filters in your app for business logic

Page 32: Nginx: Accelerate Rails, HTTP Tricks

Separate concerns:

‣Filters in your app for business logic

‣Filters in your http router for server infrastructure

Page 33: Nginx: Accelerate Rails, HTTP Tricks

Separate concerns:

‣Filters in your app for business logic

‣Filters in your http router for server infrastructure

‣Filters in either for application infrastructure

Page 34: Nginx: Accelerate Rails, HTTP Tricks

application infrastructure

Separate concerns:

‣Filters in your app for business logic

‣Filters in your http router for server infrastructure

‣Filters in either for

Page 35: Nginx: Accelerate Rails, HTTP Tricks

Custom Nginx modulesTime to get hardcore:

Page 36: Nginx: Accelerate Rails, HTTP Tricks

http://emiller.info/nginx-modules-guide.html

Page 37: Nginx: Accelerate Rails, HTTP Tricks

Granular user access control

The problem:

Page 38: Nginx: Accelerate Rails, HTTP Tricks

before_filterThe Rails solution:

Page 39: Nginx: Accelerate Rails, HTTP Tricks

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

Page 40: Nginx: Accelerate Rails, HTTP Tricks

Can we do this withouttouching the Rails app’scode?

Page 41: Nginx: Accelerate Rails, HTTP Tricks

input filter moduleThe Nginx solution:

Page 42: Nginx: Accelerate Rails, HTTP Tricks

input filter moduleThe Nginx solution:

ngx_heroku_gate

Page 43: Nginx: Accelerate Rails, HTTP Tricks

before_filter :authorize

Page 44: Nginx: Accelerate Rails, HTTP Tricks

static ngx_int_tngx_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;}

before_filter :authorize

Page 45: Nginx: Accelerate Rails, HTTP Tricks

def authorize @user = User.find(session[:user_id]) @resource = request.env['REQUEST_URI']

Page 46: Nginx: Accelerate Rails, HTTP Tricks

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);

def authorize @user = User.find(session[:user_id]) @resource = request.env['REQUEST_URI']

Page 47: Nginx: Accelerate Rails, HTTP Tricks

redirect_to '/login' unless @user

Page 48: Nginx: Accelerate Rails, HTTP Tricks

if (!user){ redirect_to(req, '/login'); return NGX_HTTP_MOVED_TEMPORARILY;}

redirect_to '/login' unless @user

Page 49: Nginx: Accelerate Rails, HTTP Tricks

redirect_to '/access_denied' unless @user.can_access(@resource)

Page 50: Nginx: Accelerate Rails, HTTP Tricks

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

redirect_to '/access_denied' unless @user.can_access(@resource)

Page 51: Nginx: Accelerate Rails, HTTP Tricks

#define X_HEROKU_USER "X-Heroku-User"

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

Page 52: Nginx: Accelerate Rails, HTTP Tricks

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

Page 53: Nginx: Accelerate Rails, HTTP Tricks

static ngx_int_tngx_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; }}

The Nginx solution: input filter

Page 54: Nginx: Accelerate Rails, HTTP Tricks

A word on performance

Page 55: Nginx: Accelerate Rails, HTTP Tricks

Closing thoughts /the future

Page 56: Nginx: Accelerate Rails, HTTP Tricks

HTTP is the enablingprotocol for the eraof cloud computing

Page 57: Nginx: Accelerate Rails, HTTP Tricks

http://igvita.com/2008/02/11/nginx-and-memcached

http://nginx.ru

Adam Wigginshttp://adam.blog.heroku.com

http://emiller.info/nginx-modules-guide.html