Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx...

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

Transcript of Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx...

Page 1: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Nginx:Accelerate Rails,HTTP Tricks

Adam WigginsRailsconf 2008

Page 2: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Nginx is a webserver

Page 3: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Nginx replaces ApacheWhich means:

Page 4: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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

Nginx replaces Apache

Page 5: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

But more importantly:

Page 6: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

But more importantly:

Nginx is a better fitfor Rails

Page 7: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Apache is the right tool:

!mod_php!owning your own server hardware

Page 8: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

!Rails!cloud computing

The era now upon us:

Page 10: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Which both work best with proxying.

!Rails!cloud computing

The era now upon us:

Page 11: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Proxying is Nginx’sprimary mechanism forserving dynamic content

Page 12: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

“One thing”

Page 13: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Embrace the constraintof keeping applicationVMs out of the front-endwebserver

Page 14: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Ok cool.

Page 15: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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

Ok cool.

Page 16: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Nginx is not a webserver?

Page 17: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Nginx is an HTTP router

Page 18: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:
Page 19: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:
Page 20: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:
Page 21: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:
Page 22: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:
Page 23: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Enough abstraction;let’s see some code

Page 24: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Filtering

Page 28: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Filtering is reaching inand tinkering withrequests and responses

Page 29: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:
Page 30: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Separate concerns:

Page 31: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Separate concerns:

!Filters in your app for business logic

Page 32: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Separate concerns:

!Filters in your app for business logic

!Filters in your http router for server infrastructure

Page 33: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Custom Nginx modulesTime to get hardcore:

Page 36: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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

Page 37: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Granular user access control

The problem:

Page 38: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

before_filterThe Rails solution:

Page 39: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Can we do this withouttouching the Rails app’scode?

Page 41: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

input filter moduleThe Nginx solution:

Page 42: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

input filter moduleThe Nginx solution:

ngx_heroku_gate

Page 43: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

before_filter :authorize

Page 44: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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;

}

before_filter :authorize

Page 45: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

def authorize

@user = User.find(session[:user_id])

@resource = request.env['REQUEST_URI']

Page 46: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

redirect_to '/login' unless @user

Page 48: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

if (!user)

{

redirect_to(req, '/login');

return NGX_HTTP_MOVED_TEMPORARILY;

}

redirect_to '/login' unless @user

Page 49: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

redirect_to '/access_denied' unless

@user.can_access(@resource)

Page 50: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

#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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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 - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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;

}

}

The Nginx solution: input filter

Page 54: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

A word on performance

Page 55: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

Closing thoughts /the future

Page 56: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

HTTP is the enablingprotocol for the eraof cloud computing

Page 57: Nginx: Accelerate Rails, HTTP Tricks - O'Reilly Mediaassets.en.oreilly.com/1/event/6/Custom Nginx Modules_ Accelerate Rails, HTTP Tricks...Nginx replaces Apache. But more importantly:

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