Download - Introduzione a Node.js
COSE CHE NON TI ASPETTI DA JAVASCRIPT: NODE.JS
Chi siamo
Luciano Colosio
Michele Capra
SA & Dev @ Save The Mom
Dev @ OrangeCode
@unlucio
@piccoloaiutante
Cosa vedremo oggiChe cos’è Node.JS
Dove nasce
ContesB in cui usarlo
Il mondo asincrono
Demo Live
Deploy su un servizio free (Heroku)
Che cos’è Node.JS
Javascirpt runBme basato su V8
Event Driven I/O server-‐side
Da dove nasce
Riprodurre il comportamento in “push” mostrato da gmail
Superare i limit del one-‐way
BONUS DERIVATO
Le caraUerisBche asincrone di JS permeUono una gesBone piu’ comoda dell’I/O che costa molto
Da dove nasce
Costo dell’ I/OL1-‐cache 3 cicli
L2-‐cache 14 cicli
RAM 250 cicli
Disco 41x10^6 cicli
Network 240x10^6 cicli
Gestire le richieste
Sincrono: gesBsco una richiesta alla volta
Contro: ogni richiesta può (e fa!) da tappo alle altre
Gestire le richieste
Fork del processo
Un processo nuovo per ogni richiesta
Contro: non scala su migliaia di connessioni(ameno di non usare migliaia di servers ;))
Gestire le richieste
Un Thread nuovo per ogni richiesta
Contro: la macchina potrebbe non avere abbastanza thread disponibili, programmazione concorrente è complessa, problemi di memoria
Gestire le richieste
La scelta di node:
Singolo Thread
Niente parallelizzazione del codice
Event Loop
La logica nell’eventloop risulta bloccante:
Devo aUendere che i task terminino
Soluzione:
NON fare nulla nel maintherad
Utilizzare event driven development
Tutte le chiamate di I/O sono gestite come eventi asincroni, quindi non
bloccanti.
Event loop
non e' necessario pre carrozzarsi per le perfomarnces
(es: pre allocare thread per rispondere piu' velocemente).
Minor spreco di memoria/risorse
Minor rischio che il server vada in oveload
Importante!
Rispondere velocemente al client delegando a task attività che richiedono risorse ed i/o ad alta latenza
Il focus è sulla risposta nel minor tempo possibile
Async VS Sync
// Good: write files asynchronouslyfs.writeFile('message.txt', 'Hello Node', funcBon (err) { console.log("It's saved and the server remains responsive!");});
// BAD: write files synchronouslyfs.writeFileSync('message.txt', 'Hello Node');console.log("It's saved, but you just blocked ALL requests!");
Esempio Architettura
Le scritture dei logs non sono piu’ un problema!
User NODE
NODE
Client Web Engine
Database
Logging facility Mass storage(big slow disk)
DB
Disk
Esempio di contesti
Web API
Realtime web services (chat, push, peppertweet)
Chi lo usa:
https://github.com/joyent/node/wiki/Projects,-Applications,-and-Companies-Using-Node
37signalsAjax.org - Cloud9 IDE
eBayTrelloKlout
LinkedinMicrosoft
VoxerYahoo!
JS: V8 in Node
Stesso motore del browser ma:
non c’è DOM
tutto gira nell’Event Loop
non c’è JQuery che tenga
programmazione asincrona
ESEMPI DI APPS
Menamo le mani in pasta :)
App Esempio
var http = require('http');
var server = http.createServer(function (request, response) { response.writeHead(200, {"Content-Type": "text/plain"}); response.end("Hello World\n");});
server.listen(8000);
console.log("Server running at http://127.0.0.1:8000/");
HUp Hello World, la piu’ semplice node app:
App Esempio
var server = require('./lib/node-‐router').getServer();
server.get("/json", funcBon (req, res, match) { return {hello: "World"};});
server.get(new RegExp("^/(.*)$"), funcBon hello(req, res, match) { return "Hello " + (match || "World") + "!";});
server.listen(8080);
Http Hello World, basta una lib ed ecco un servizio REST
App Esempio
Vi ricordate IRC?
NO?!?!?!
Ok, ce l’aspeUavamo ;P
Oggi ci ispireremo al passato per un twiUer bot:
TWITVIA
App Esempio
hUps://github.com/unlucio/tvitvia
Get the code:
App Esempio: Struttura
Moduli
DescriUoreper npm
Main File
Heroku ProcessFile (opBonal)
App Esempio: npm install
Moduli installaB
Diamogli un nome sensato :)
{ "name": "Twitvia", "descripBon": "Vintage trivia bot", "version": "0.0.1", "dependencies": { "twit" : "0.1.2", "underscore": "1.3.1", "db-‐mysql": "0.7.6" }, "engines": { "node": ">= 0.6.0" }
App Esempio
Ovviamente possiamoaggiungere directorya nostro piacimento
per parB delle nostra app
App Esempio: def. lib
var Twit = require('twit');
module.exports = (funcBon(twiUerClient) { twiUerClient = funcBon(datas) {}; twiUerClient.prototype.publishTweet = funcBon (message) {};
twiUerClient.prototype.sendMenBon = funcBon (to, message) {};
twiUerClient.prototype.sendDM = funcBon (to, message) {}; twiUerClient.prototype.followUser = funcBon (user) {}; return twiUerClient;})();
App Esempio: use libvar TweUerClient = require('./lib/twiUerClient'),
var tClient = new TweUerClient({ consumer_key: 'getItFromTwiUer', consumer_secret: 'getItFromTwiUer', access_token: 'getItFromTwiUer', access_token_secret: 'getItFromTwiUer',});
funcBon getCommand(tweet) {[...]}
tClient.T.stream('user',[], funcBon (stream) { stream.on('tweet', funcBon (tweet) { getCommand(tweet) });});
App Esempio: model objsvar _ = require('underscore');
module.exports = (funcBon(quesBons) { quesBons = funcBon(db, tweeterClient) { this.db = db; this.tweeterClient = tweeterClient; }; quesBons.prototype.publishRandom = funcBon() {}; quesBons.prototype.getRandom = funcBon (quesBonsList) {}; quesBons.prototype.selectAll = funcBon(callback) {}; quesBons.prototype.setAnswered = funcBon(refTweetID, callback) {} return quesBons;})();
App Esempio: model objs
module.exports = (funcBon(answers) { answers = funcBon(db, tweeterClient) { this.db = db; this.tweeterClient = tweeterClient; }; answers.prototype.checkMatch = funcBon (refTweetID, userAnswer, callback) { };
return answers;})();
App Esempio: model objsmodule.exports = (funcBon(users) { users = funcBon(db, tweeterClient) { this.db = db; this.tweeterClient = tweeterClient; }; users.prototype.find = funcBon(userName, callback) {}; users.prototype.add = funcBon(userName, callback) {}; users.prototype.capture = funcBon(userName, callback) {}; users.prototype.scorePoint = funcBon(userName, callback) {}; users.prototype._updateScore = funcBon(userID, thePlayer, callback){}; return users;})();
App Esempio: togethervar mysql = require('db-‐mysql'), TweUerClient = require('./lib/twiUerClient'), Users = require('./model/users'), QuesBons = require('./model/quesBons'), Answers = require('./model/answers');
var myDb = new mysql.Database({[connecBon datas]
});
[...]
var tClient = new TweUerClient({[api datas]
});
var users = new Users(myDb, tClient);var quesBons = new QuesBons(myDb, tClient);var answers = new Answers(myDb, tClient);
tClient.T.stream('user',[], funcBon (stream) { stream.on('tweet', funcBon (tweet) { getCommand(tweet) });});
Deploy & hostingheroku login
Compiliamo il Procfileweb: node <mainscript.js>
git initgit add .
git commit -‐m “<commento>”heroku create -‐-‐stack cedargit push heroku masterheroku ps:scale web=1
Nella realta’
Un esempio famoso ed eclatante di uBlizzo di node:
Linkedin!
Dove lo usano?Linkedin usa node come middle layer tra i server di backend ed i
client mobile
backend server
Mobile client
NodeJs instances
Mobile Client
I 10 consigli per node.jsEvitare il codice sincoronoNo socket polling!Non usare node.js per servire asset staBciDelegare il rendering al clientUsare gzip tra i vari componenBParallelizzare al piu’ possibile!Se possibile: NO SESSIONSUsare moduli binari anzicche’ in javascriptUsare javascript standard anzicche’ librerie faUe per i clientTenere il codice piccolo e compaUo
Grazie per l’attenzione
se volete, trollateci su twiUer@unlucio -‐ @piccoloaiutante
Un po’ di spam ;)
hUp://nodejsconf.ithUp://www.webdebs.org/
Cerco Dev
Scrivi a:[email protected]
Save the Mom cerca sviluppatori da integrare nel nostro team! :)
Skills:Web
MobileWebMobile applications
(iOS, wp7, android, balckberry)