Heroku pop-behind-the-sense

Preview:

DESCRIPTION

lightning talk at heroku

Citation preview

POPBehind the sense

Ben Lin

Co-founder at WOOMOO INC.

A full time entrepreneur & JavaScript lover

Fall in love with node.js on Jun 2011

dreamerslab.comben@dreamerslab.com

twitter.com/dreamerslabgithub.com/dreamerslab

About me

About me

COKE - Full stack node.js MVC framework

Vodka - Functional testing frameworkThunder - The lightning fast template engine

And a lot more on

https://github.com/dreamerslab

Agenda

1. Software architecture

2. Frameworks & Libraries

3. Application stack

4. Packages

5. Scaling node.js

6. Deployment

7. Q & A

Software architecture

Software architecture

Home brewed node.js MVC framework - COKE

Why node.js?

It’s fast and easy to scale horizontally

Software architectureRestful router for api & web server

module.exports = function ( map ){ map.get( 'api', 'api/home#index' ); map.namespace( 'api', function ( api ){ api.resources( 'users', { only : [ 'create', 'show', 'update', 'destroy' ] }, function ( users ){ users.get( 'projects/:id/full', 'user_projects#full' ); users.resources( 'user_projects', { path : 'projects', only : [ 'create', 'index', 'show', 'update', 'destroy' ] }); // more routes ...... });};

Software architecture

var form = require( 'express-form2' );var field = form.field;var r = require( '../regex' );

module.exports = {

validate_create : form( field( 'client_id' ).required().is( r.id, '01' ), field( 'mockup_id' ).required().is( r.id, '01' ), field( 'format' ).required().is( r.img, '014' ) ),

validate_index : form( field( 'mockup_id' ).required().is( r.id, '01' ) ),

validate_destroy : form( field( 'mockup_id' ).required().is( r.id, '01' ), field( 'id' ).required().is( r.id, '01' ) )};

make sure all the arguments are correct before get into controllersValidation

Software architectureOnly do data exchange & flow controlController

module.exports = Application.extend({

init : function ( before, after ){ before( this.is_authenticated ); before( this.validate_create ); before( this.has_file ); before( this.is_validate ); },

create : function ( req, res, next ){ var self = this;

ProjectImage.insert( req.form, next, function (){ self.forbidden( res ); }, function (){ self.frozen( res ); }, function ( img ){ self.created( res, img ); }); }});

Software architecture

Handel business logic and model relations, we add a wrapper on mongoose the ODM.

Model

module.exports = { virtuals : [ 'image' ], hooks : { pre : { save : [ common.mark_new ], remove : [ common.backup_to( 'BakMockupImage' ), hooks.remove_from_mockup ] }, post : { save : [ hooks.add_to_mockup, common.add_to_auth( 'images' )], remove : [ hooks.remove_from_s3 ] } }, statics : { insert : function ( args, next, forbidden, frozen, created ){ ... }, index : function ( args, next, no_content, forbidden, ok ){ .. }, destroy : function ( args, next, no_content, forbidden, frozen, deleted ){ ... } }, methods : { is_owner : function ( user_id ){ ... }, created : function (){ ... }, gen_url : function ( format ){ ... } }};

Software architecture

We use the fastest template engine thunder ( home brewed )

View

<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title><?= it.title ?></title> <meta name="keywords" content="<?= it.keywords || '' ?>" /> <meta name="description" content="<?= it.description || '' ?>" /> <!--[if lt IE 9]> <meta http-equiv="refresh" content="0; url=/no-ie"> <![endif]--> <?= it.css( it.styles ) ?> </head> <body> <? it.reset_asset_host(); ?> <?= it.body ?> <?= it.js( it.scripts ) ?> </body></html>

Software architecture

Extract reusable codes that is not relevant to model

Libraries

Scaling node.js

Start small with built-in static server, node.js app & database all on the same server.

Scaling node.js

Use nginx as static server for better performance.

Scaling node.js

Use nginx as as proxy server as well to load balance requests.

The number of node.js app instance depends on how many CPU cores on the machine.

Scaling node.js

Split static files to different server for easier maintenance.

Scaling node.js

Use aws S3 for easier setup and maintenance.

Scaling node.js

Split database to another server. Make the node.js app server an unit.

Scaling node.js

Add a load balancer, add more app unit as the site scales up.

Scaling node.js

Add replica set if the database hits its limit.

Scaling node.js

Add CDN for static files for cross reign performance.

Scaling node.js

Split app to difference services as it scales up. Previous scaling steps apply to those services too.

Scaling node.js

Deployment

With ssh, git; The server must stop during deployment.

Deployment

With ssh, git; 0 downtime deployment is possible since we have more than 1 instance( repo ).

Deployment

With ssh, git; Split static file makes it easier to deploy with multi instance( repo ) app.

Deployment

Deploying with multi machine it’s better to use image files on aws ec2.

Deployment

THE ENDThanks

QUESTIONS?