• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Всеволод Струкчинский: Node.js
 

Всеволод Струкчинский: Node.js

on

  • 7,728 views

 

Statistics

Views

Total Views
7,728
Views on SlideShare
653
Embed Views
7,075

Actions

Likes
0
Downloads
4
Comments
0

3 Embeds 7,075

http://tech.yandex.ru 7058
https://tech.yandex.ru 15
http://news.google.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

    Всеволод Струкчинский: Node.js Всеволод Струкчинский: Node.js Presentation Transcript

    • @floatdrop bit.ly/nodejs-­‐‑shri
    • Node.JS
    • History bit.ly/crcfd
    •   1987
    • 1 2 on mouseUp 3 get the selection 4 if it is empty then as "Dial what number?" 5 if it is not empty then 6 push this card 7 visual effect zoom open 8 go to stack "Phone" 9 dial it 10 pop card 11 end if 12 end mouseUp 13 1987
    • 1995
    • Расчитан  на  обработку  событий 1995
    • Расчитан  на  обработку  событий Был  написан  за   1995  дней
    • Расчитан  на  обработку  событий Был  написан  за   10  дней 1995
    • Расчитан  на  обработку  событий 10 Был  написан  за    дней Function  as  first-­‐‑class  objects 1995
    • Расчитан  на  обработку  событий 10 Был  написан  за    дней Function  as  first-­‐‑class  objects Прототипное  наследование  из  Self 1995
    • 2005
    • 2005
    • AJAX 2005
    • 2009
    • Node.JS JavaScript  on  server 2009
    • Apache  +  PHP  =  ❤
    • Apache  +  PHP  =  ❤
    • index.php 1 2 3 4 5 6 7 8 9 $result = mysqli_query( $con, "SELECT * FROM Persons"); while($row = mysqli_fetch_array($result)) { echo $row['Name']."n"; } file_put_contents("access.log", "Request done")
    • Single-­‐‑thread  server Pictures  from  node-­‐‑explained
    • Single-­‐‑thread  server Pictures  from  node-­‐‑explained
    • Single-­‐‑thread  server Pictures  from  node-­‐‑explained
    • Single-­‐‑thread  server Pictures  from  node-­‐‑explained
    • Single-­‐‑thread  server Pictures  from  node-­‐‑explained
    • Multi-­‐‑thread  server
    •    
    • Ryan  Dahl    
    • Ryan  Dahl   I/O  has  to  be  done  differently. We  are  doing  it  wrong  
    • Ryan  Dahl   I/O  has  to  be  done  differently. We  are  doing  it  wrong   bit.ly/jsconf-­‐‑node
    • event-­‐‑loop  сервер
    • event-­‐‑loop  сервер
    • event-­‐‑loop  сервер
    • event-­‐‑loop  сервер
    • event-­‐‑loop  сервер
    • event-­‐‑loop  сервер
    • event-­‐‑loop  сервер
    • event-­‐‑loop  server
    • bit.ly/bombanulo
    • event-­‐‑loop  server goes  wrong
    • JavaScript  is  slow bit.ly/bombanulo-­‐‑2
    • "ʺSimple"ʺ  benchmark bit.ly/dumb-­‐‑test
    • Installing nodejs.org/download
    • Running
    • Running
    • Running
    • Running
    • windows
    • window
    • document
    • document
    • global
    • global
    • global
    • process
    • process
    • process
    • Modules require('ʹantigravity'ʹ)
    • module.js 1 2 3 4 5 function HelloWorld () { console.log('Hello world'); } console.log('Module loaded');
    • index.js 1 require('./module');
    • index.js 1 2 3 require('./module'); HelloWorld();
    • module.js 1 2 3 4 5 6 7 function HelloWorld () { console.log('Hello world'); } console.log('Module loaded'); exports.HelloWorld = HelloWorld;
    • index.js 1 2 3 var module = require('./module'); module.HelloWorld();
    • module.js 1 2 3 4 5 6 7 function HelloWorld () { console.log('Hello world'); } console.log('Module loaded'); global.HelloWorld = HelloWorld;
    • index.js 1 2 3 require('./module'); HelloWorld();
    • exports  vs  module.exports
    • exports  vs  module.exports russian.js 1 2 3 4 5 6 var en_translation = { yes: 'Нет', no: 'Да' }; exports = en_translation;
    • exports  vs  module.exports russian.js 1 2 3 4 5 6 var en_translation = { yes: 'Да', no: 'Нет' }; module.exports = en_translation;
    • exports  vs  module.exports russian.json { "yes": "да", "no": "нет" }
    • requrie('ʹ./directory'ʹ)
    • requrie('ʹ./directory'ʹ) 3.   require('ʹ./directory/index.json'ʹ)
    • requrie('ʹ./directory'ʹ) 3.   require('ʹ./directory/index.json'ʹ) 2.   require('ʹ./directory/index.js'ʹ)
    • requrie('ʹ./directory'ʹ) 3.   require('ʹ./directory/index.json'ʹ) 2.   require('ʹ./directory/index.js'ʹ) 1.   require('ʹ./directory/'ʹ  + require('ʹ./directory/package.json'ʹ).main);
    • require('http') require('express') require('./index.js') require('./config.json') require('./module') // Directory
    • Simple  web-­‐‑server
    • Simple  web-­‐‑server
    • Simple  web-­‐‑server
    • Simple  web-­‐‑server
    • Simple  web-­‐‑server
    • Simple  web-­‐‑server index.js 1 2 3 4 5 6 7 8 9 var http = require('http'); function helloService(request, response) { response.end("Hello, stranger!"); } var server = http.createServer(helloService); module.exports = server;
    • Run,  Forest,  Run!
    • Run,  Forest,  Run!
    • Run,  Forest,  Run!
    • Run,  Forest,  Run!
    • Simple  web-­‐‑server node_modules
    • Run,  Forest,  Run!
    • Run,  Forest,  Run!
    • Run,  Forest,  Run!
    • Run,  Forest,  Run!
    • require("ʺantigravity"ʺ) in  /home/user/programm/library/index.js
    • require("ʺantigravity"ʺ) in  /home/user/programm/library/index.js 1.   /home/user/programm/library/node_modules/antigravity
    • require("ʺantigravity"ʺ) in  /home/user/programm/library/index.js 1.   /home/user/programm/library/node_modules/antigravity 2.   /home/user/programm/node_modules/antigravity
    • require("ʺantigravity"ʺ) in  /home/user/programm/library/index.js 1.   /home/user/programm/library/node_modules/antigravity 2.   /home/user/programm/node_modules/antigravity 3.   /home/user/node_modules/antigravity
    • require("ʺantigravity"ʺ) in  /home/user/programm/library/index.js 1.   /home/user/programm/library/node_modules/antigravity 2.   /home/user/programm/node_modules/antigravity 3.   /home/user/node_modules/antigravity 4.   /home/node_modules/antigravity
    • require("ʺantigravity"ʺ) in  /home/user/programm/library/index.js 1.   /home/user/programm/library/node_modules/antigravity 2.   /home/user/programm/node_modules/antigravity 3.   /home/user/node_modules/antigravity 4.   /home/node_modules/antigravity 5.   /node_modules/antigravity
    • require("ʺantigravity"ʺ) in  /home/user/programm/library/index.js 1.   /home/user/programm/library/node_modules/antigravity 2.   /home/user/programm/node_modules/antigravity 3.   /home/user/node_modules/antigravity 4.   /home/node_modules/antigravity 5.   /node_modules/antigravity NODE_PATH
    • require("ʺantigravity"ʺ) in  /home/user/programm/library/index.js 1.   /home/user/programm/library/node_modules/antigravity 2.   /home/user/programm/node_modules/antigravity 3.   /home/user/node_modules/antigravity 4.   /home/node_modules/antigravity 5.   /node_modules/antigravity NODE_PATH $HOME/.node_modules,  $HOME/.node_libraries,  $PREFIX/lib/node
    • node_modules/antigravity.js 1 module.exports = new Date(); index.js 1 console.log(require("antigravity"));
    • node_modules/antigravity.js 1 2 3 console.log(module); module.exports = new Date();
    • Circular  dependencies
    • Circular  dependencies a.js 1 2 var b = require('./b.js'); console.log("B: ", b); b.js 1 2 var a = require('./a.js'); console.log("A: ", a);
    • Circular  dependencies a.js 1 2 3 4 module.exports.hello = "Hello from A"; var b = require('./b.js'); module.exports.helloFromB = b.hello; console.log("B: ", b); b.js 1 2 3 4 module.exports.hello = "Hello from B"; var a = require('./a.js'); module.exports.helloFromA = a.hello; console.log("A: ", a);
    • modulecounts.com
    • Installing  module
    • Installing  module
    • Installing  module
    • Installing  module
    • Installing  module
    • Nested  dependencies pros  /  cons
    • Nested  dependencies pros  /  cons +  Version  independent
    • Nested  dependencies pros  /  cons +  Version  independent -­‐‑  Wieght  more
    • package.json { } "name": "express", "version": "3.4.4", "dependencies": { "connect": "2.11.0", "commander": "1.3.2", "range-parser }, "devDependencies": { "ejs": "*", "mocha": "*", "jade": "0.30.0", "hjs": "*", " }, "main": "index", "bin": { "express": "./bin/express" }, "scripts": { "prepublish": "npm prune", "test": "make test" }, "engines": { "node": "*" }
    • Express  application var express = require('express'); var app = express(); app.get('/', function(req, res) { res.end('Hello!'); }); app.listen(3000);
    • Event  loop
    • bit.ly/kantor-­‐‑node
    • joyent/node  -­‐‑  node.cc
    • joyent/node  -­‐‑  env-­‐‑inl.h
    • joyent/node  -­‐‑  env-­‐‑inl.h
    • joyent/libuv  -­‐‑  loop.c
    • joyent/libuv  -­‐‑  loop.c 1 static int uv__loop_init(uv_loop_t* loop, int default_loop) { 2 // ... 3 RB_INIT(&loop->timer_handles); 4 QUEUE_INIT(&loop->wq); 5 QUEUE_INIT(&loop->active_reqs); 6 QUEUE_INIT(&loop->idle_handles); 7 QUEUE_INIT(&loop->async_handles); 8 QUEUE_INIT(&loop->check_handles); 9 QUEUE_INIT(&loop->prepare_handles); 10 QUEUE_INIT(&loop->handle_queue); 11 QUEUE_INIT(&loop->pending_queue); 12 QUEUE_INIT(&loop->watcher_queue); 13 14 err = uv__platform_loop_init(loop, default_loop); 15 // ... 16 }
    • uv__platform_loop_init kqueue epoll
    • joyent/node  -­‐‑  node.cc
    • joyent/node  -­‐‑  core.c   :  258 1 int uv_run(uv_loop_t* loop, uv_run_mode mode) { 2 r = uv__loop_alive(loop); 3 while (r != 0 && loop->stop_flag == 0) { 4 // ... 5 uv__update_time(loop); 6 uv__run_timers(loop); 7 uv__io_poll(loop, timeout); 8 // ... 9 } 10 } 1 2 3 4 5 static int uv__loop_alive(uv_loop_t* loop) { return uv__has_active_handles(loop) || uv__has_active_reqs(loop) || loop->closing_handles != NULL; }
    • Fibonacci 1 2 3 4 5 6 7 8 9 10 function fibonacci(n) { if (n < 2) return 1; else return fibonacci(n-2) + fibonacci(n-1); } require('http').createServer(function (req, res) { res.end("40: " + fibonacci(40)); }).listen(8005);
    • Fibonacci Requests per second: 0.61 Time per request: 1634.748 ms (vs 5676 ms)
    • setTimeout,  setImmediate, process.nextTick
    • 1.   process.nextTick
    • 1.   process.nextTick* 2.   Input  /  Output
    • 1.   process.nextTick* 2.   Input  /  Output 3.   setImmediate
    • 1.   process.nextTick* 2.   Input  /  Output 3.   setImmediate 4.   setTimeout
    • Fibonacci 1 2 3 4 5 6 7 8 9 10 11 12 function fibonacci(i, n, f1, f2, res) { if (i >= n) res.end(n + ": " + (f1 + f2)); else setImmediate(function() { fibonacci(i + 1, n, f2, f1 + f2, res); }); } require('http').createServer(function (req, res) { fibonacci(0, 1473, 1, 1, res); }).listen(8005);
    • Fibonacci Requests per second: 264.55 Time per request: 3.780 ms
    • Streams bit.ly/streams-­‐‑node
    • Streams 0.10.x bit.ly/streams-­‐‑node
    • 1 $ cut -f 1 | uniq -c | sort -n
    • Streams  in  Node.JS
    • Streams  in  Node.JS 1.   fs  -­‐‑  createReadStream,  createWriteStream
    • Streams  in  Node.JS 1.   fs  -­‐‑  createReadStream,  createWriteStream 2.   process  -­‐‑  stdin,  stderr  and  stdout
    • Streams  in  Node.JS 1.   fs  -­‐‑  createReadStream,  createWriteStream 2.   process  -­‐‑  stdin,  stderr  and  stdout 3.   http  -­‐‑  client  requests,  server  response
    • Streams  in  Node.JS 1.   fs  -­‐‑  createReadStream,  createWriteStream 2.   process  -­‐‑  stdin,  stderr  and  stdout 3.   http  -­‐‑  client  requests,  server  response 4.   tcp  -­‐‑  sockets
    • Streams  in  Node.JS 1.   fs  -­‐‑  createReadStream,  createWriteStream 2.   process  -­‐‑  stdin,  stderr  and  stdout 3.   http  -­‐‑  client  requests,  server  response 4.   tcp  -­‐‑  sockets 5.   zlib  -­‐‑  createUnzip...
    • Streams  in  Node.JS 1.   fs  -­‐‑  createReadStream,  createWriteStream 2.   process  -­‐‑  stdin,  stderr  and  stdout 3.   http  -­‐‑  client  requests,  server  response 4.   tcp  -­‐‑  sockets 5.   zlib  -­‐‑  createUnzip... 6.   crypto  -­‐‑  createCipher
    • Crypto  service 1 var app = require('express')();
    • Crypto  service 1 var app = require('express')(); 1 2 3 4 app.post('/:algo/:secret', function(req, res) { // Some magic should be applied here res.end(req.params.algo + " " + req.params.secret); });
    • Crypto  service 1 var app = require('express')(); 1 2 3 4 app.post('/:algo/:secret', function(req, res) { // Some magic should be applied here res.end(req.params.algo + " " + req.params.secret); }); 1 app.listen(31337);
    • Crypto  stdin 1 2 3 4 5 6 var cipher = require('crypto') .createCipher('aes192', 'secret'); process.stdin.pipe(cipher).pipe(process.stdout);
    • Crypto  service 1 var app = require('express')(); 1 2 3 4 5 app.get('/:algo/:secret', function(req, res) { var cipher = require('crypto') .createCipher(req.params.algo, req.params.secret); req.pipe(cipher).pipe(res); }); 1 app.listen(31337);
    • Push  vs  Pull  streams
    • Pull  streams
    • Push  streams
    • Streams  in  Node.JS  are  Push
    • ReadableStream.  Events: data,  end,  close,  error,  readable
    • ReadableStream data  event 1 2 3 4 process.stdin.on('data', function(chunk) { console.log(chunk); });
    • WriteableStream.  Events finish,  pipe,  unpipe,  drain
    • WriteableStream.  Methods write  method 1 var backpressure = process.stdout.write('data');
    • Writeable  stream backpressure 1 var backpressure = process.stdout.write('data');
    • Writeable  stream backpressure 1 var backpressure = process.stdout.write('data'); This  return  value  is  strictly  advisory.  You  MAY  continue to  write,  even  if  it  returns  false.  However,  writes  will  be buffered  in  memory,  so  it  is  best  not  to  do  this excessively.  Instead,  wait  for  the  drain  event  before writing  more  data.