NodeJS Эффективное программирование  Юра Богданов технический директор и соучредитель Eventr
NodeJS <ul><li>Цель   проекта: </li></ul>«Предоставить  естественную  неблокирующую ,  событийно-ориентированную инфрастру...
NodeJS <ul><li>NodeJS   – серверная  JavaScript  платформа </li></ul><ul><ul><li>Использует  Google V 8  (Chromium: Google...
Для чего   подходит NodeJS <ul><li>Много  I/O  +  большая конкурентность </li></ul><ul><ul><li>RIA —  «богатые»   приложен...
Event loop <ul><li>Это цикл   (libev) </li></ul><ul><li>Это один процесс, один поток </li></ul><ul><li>Выполняет одну зада...
Время <ul><li>CPU  –  процессорное время </li></ul><ul><ul><li>Интерпретация кода </li></ul></ul><ul><ul><li>Бизнес-логика...
<ul><li><?php </li></ul><ul><li>$user = $db->query('SELECT * FROM users WHERE id=1');  // I/O - 70ms </li></ul><ul><li>$ht...
<ul><li><?php </li></ul><ul><li>$user = $db->query('SELECT * FROM users WHERE id=1');   // I/O - 70ms </li></ul><ul><li>$h...
<ul><li><?php </li></ul><ul><li>$user = $db->query('SELECT * FROM users WHERE id=1');   // I/O - 70ms </li></ul><ul><li>$h...
Blocking I/O callback I/O I/O CPU CPU занято свободно Event Loop монолит А что если во время ожидания  I/O  заниматься дру...
I/O Event loop Примерно так выглядит более реальный запрос: CPU+I/O
I/O CPU  callback I/O CPU Event loop Примерно так выглядит более реальный запрос:
Event loop Примерно так выглядит более реальный запрос: I/O CPU  Свободно для других задач callback I/O CPU
Event Loop mysql.query(‘SELECT count(*) FROM users’, function(err, count) { console.log(‘There are %d users in db’, count)...
Event Loop mysql.query(‘SELECT count(*) FROM users’, function(err, count) { console.log(‘There are %d users in db’, count)...
Event Loop mysql.query(‘SELECT count(*) FROM users’, function(err, count) { console.log(‘There are %d users in db’, count)...
<ul><li><?php </li></ul><ul><li>$user = $db->query('SELECT * FROM users WHERE id=1');  // I/O - 70ms </li></ul><ul><li>$ht...
<ul><li><?php </li></ul><ul><li>$user = $db->query('SELECT * FROM users WHERE id=1');  // I/O - 70ms </li></ul><ul><li>$ht...
Первый запрос Blocking I/O, 1  процесс
Второй запрос, после 10 ms ожидает выполнения первого Blocking I/O, 1  процесс
Третий запрос, после 50 ms ожидает выполнения первого и второго Blocking I/O, 1  процесс
Blocking I/O, 1  процесс Event loop, 1  процесс
Blocking I/O, 1  процесс Event loop, 1  процесс Время: 0 ms Пришел первый запрос, Запрашиваем  I/O,  освобождаемся , Ждем ...
Blocking I/O, 1  процесс Event loop, 1  процесс Время: 10 ms Пришел второй запрос, Запрашиваем  I/O,  освобождаемся , Ждем...
Blocking I/O, 1  процесс Event loop, 1  процесс Время: 50 ms Пришел третий запрос, Запрашиваем  I/O,  освобождаемся , Ждем...
Blocking I/O, 1  процесс Event loop, 1  процесс Время: 70 ms Пришел ответ на  I/O  первого запроса ,  запускаем  callback 1
Blocking I/O, 1  процесс Event loop, 1  процесс Время: 80 ms Пришел ответ на  I/O  второго запроса,  callback 2   ожидает ...
Blocking I/O, 1  процесс Event loop, 1  процесс Время: 1 0 0 ms с allback 1   завершился, запускаем  callback 2
Blocking I/O, 1  процесс Event loop, 1  процесс Время:  12 0 ms Пришел ответ на  I/O  третьего запроса,  callback 3   ожид...
Blocking I/O, 1  процесс Event loop, 1  процесс Время: 130 ms с allback 2   завершился, запускаем  callback 3
Blocking I/O, 1  процесс Event loop, 1  процесс Время: 160 ms callback 3   завершился Ждем других запросов
Время  CPU vs I/O RIA  трэнд
Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_mo...
Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_mo...
Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_mo...
Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_mo...
Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_mo...
Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_mo...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>res.wri...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.wr...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>res.wri...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>res.wri...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.wr...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.wr...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.wr...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.wr...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.wr...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.wr...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.wr...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>setTime...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>setTime...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>setTime...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>var i = 0; </li></ul><ul><li>http.createServer(function(req, re...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>var i = 0; </li></ul><ul><li>http.createServer(function(req, re...
HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>var i = 0; </li></ul><ul><li>http.createServer(function(req, re...
Callback-driven  парадигма <ul><li>Ломает мозг </li></ul><ul><li>Синтаксический шум </li></ul><ul><li>С ложно выполнить ря...
Callback-driven  парадигма function  asyncFunction ( arg1, arg2, argN,  callback ) { } Неблокирующая функция принимает  ca...
Callback-driven  парадигма function  asyncFunction ( arg1, arg2, argN,  callback ) { } function  callback ( err , result1,...
Callback-driven  парадигма function sum(a, b) { if (a > b) { throw new Error('a cannot be greater than b'); } return a + b...
Callback-driven  парадигма function sum(a, b) { if (a > b) { throw new Error('a cannot be greater than b'); } return a + b...
Callback-driven  парадигма function sum(a, b) { if (a > b) { throw new Error('a cannot be greater than b'); } return a + b...
Callback-driven  парадигма try { var result = sum(2, 3); console.log('result = %d', result); } catch (err) { console.error...
Callback-driven  парадигма try { var result = sum(2, 3); console.log('result = %d', result); } catch (err) { console.error...
Callback-driven  парадигма function getUser(id, callback) { }
Callback-driven  парадигма function getUser(id, callback) { } getUser(1234, function(err, user) { if (err) return console....
Callback-driven  парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) retu...
Callback-driven  парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) retu...
Callback-driven  парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) retu...
Callback-driven  парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) retu...
Callback-driven  парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) retu...
Callback-driven  парадигма Error: User not found at afterDbConnect (/path/to/script.js:24:14) at /path/to/script.js:20:9 a...
Callback-driven  парадигма Error: User not found at  afterDbConnect  (/path/to/script.js:24:14) at /path/to/script.js:20:9...
Callback-driven  парадигма function getUser(id, callback) { readConfig(‘config.json’,  function(err, config){ if (err) ret...
Callback-driven  парадигма function getUser(id, callback) { readConfig(‘config.json’,  function(err, config){ if (err) ret...
node-sync Function.prototype.sync = function(context, arguments…) <ul><li>Использует сопрограммы  (coroutines )   с++ </li...
var Sync = require(‘sync’); function getUser(id, callback) { Sync(function(){ var config = readConfig.sync(null, ‘config.j...
var Sync = require(‘sync’); function getUser(id, callback) { Sync(function(){ var config = readConfig.sync(null, ‘config.j...
var Sync = require(‘sync’); function getUser(id, callback) { Sync(function(){ var config = readConfig.sync(null, ‘config.j...
var Sync = require(‘sync’); function getUser(id) { var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.s...
var Sync = require(‘sync’); function getUser(id) { var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.s...
var Sync = require(‘sync’); function getUser(id) { var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.s...
var Sync = require(‘sync’); function getUser(id) { var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.s...
var Sync = require(‘sync’); function getUser(id) { var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.s...
Callback-driven  парадигма $pages = $db->fetchRows(‘SELECT * FROM pages’); foreach ($pages as $page) { $contents = fetchUr...
Callback-driven  парадигма $pages = $db->fetchRows(‘SELECT * FROM pages’); foreach ($pages as $page) { $contents = fetchUr...
Callback-driven  парадигма $pages = $db->fetchRows(‘SELECT * FROM pages’); foreach ($pages as $page) { $contents = fetchUr...
Callback-driven  парадигма $pages = $db->fetchRows(‘SELECT * FROM pages’); foreach ($pages as $page) { $contents = fetchUr...
Callback-driven  парадигма db.fetchRows(‘SELECT * FROM pages’, function(err, pages){ var narrow = new Narrow(10, function(...
Callback-driven  парадигма db.fetchRows(‘SELECT * FROM pages’, function(err, pages){ var narrow = new Narrow(10, function(...
Callback - driven  решения? <ul><li>node-sync   -  использует сопрограммы  (coroutines ) </li></ul><ul><li>streamline.js  ...
Масштабирование Nodejs – is just node   (c)  Ryan Dahl
Масштабирование Nodejs – is just node   (c)  Ryan Dahl   1 ядро  CPU  = 1  nodejs  процесс
Масштабирование <ul><li>node-cluster </li></ul><ul><ul><li>Расширяемый </li></ul></ul><ul><ul><li>Поддержка  POSIX  сигнал...
HTTP   Cluster <ul><li>var http = require(‘http’),  cluster = require(‘cluster’); </li></ul><ul><li>var server = http.crea...
HTTP   Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server =  http.crea...
HTTP   Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server =  http.crea...
HTTP   Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server = http.creat...
HTTP   Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server = http.creat...
HTTP   Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server = http.creat...
NodeJS + Много  I/O Много Запросов + Event Loop = PROFIT
Юра Богданов https://github.com/ 0 ctave Github: http://twitter.com/ yuriybogdanov Twitter: http://about.me/ bogdanov Abou...
Upcoming SlideShare
Loading in …5
×

Эффективное программирование на NodeJS

8,627 views

Published on

Доклад рассматривает тонкости nodejs, а так же преимущества Evented I/O для серверных приложений. Будет предоставлен ряд рекоммендаций по правильному построению архитектуры, модульности, масштабированию, дизайну кода. Краткое введение в технологию программирования "волокнами" (fibers) и ряд других эффективных практик.

Published in: Technology, Business
3 Comments
14 Likes
Statistics
Notes
  • Привет! Мы запилили поддержку Node.js на всех тарифных планах виртуального хостинга (не на VDS/VPS и не на облаке, а на shared!) и сейчас очень нуждаемся в обратной связи, а для этого нужно больше живых проектов на Node.js. У всех тарифов есть бесплатный тестовый период: https://sprinthost.ru. Регистрируйтесь, создавайте приложение, присылайте замечания, пожелания и вопросы на support@sprinthost.ru или в группу https://vk.com/sprinthost, мы будем бесконечно благодарны. Что нужно знать: В каталоге с приложением ( ~/domains/example.org/public_html ) создаем файл app.js со следующим содержимым: require('/home/login/domains/example.org/public_html/index.js'); process.chdir('/home/login/domains/example.org/public_html'); Создаем файл .htaccess в этом же каталоге и добавляем в него правило: PassengerStartupFile app.js PassengerResolveSymlinksInDocumentRoot on Require all granted PassengerAppType node PassengerAppRoot /home/login/domains/example.org/public_html Options -MultiViews Для работы приложений у нас используется Phusion Passenger https://www.phusionpassenger.com/#about
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • хороший туториал. почерпнул cluster.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Спасибо! Очень помогло.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
8,627
On SlideShare
0
From Embeds
0
Number of Embeds
154
Actions
Shares
0
Downloads
76
Comments
3
Likes
14
Embeds 0
No embeds

No notes for slide

Эффективное программирование на NodeJS

  1. 1. NodeJS Эффективное программирование Юра Богданов технический директор и соучредитель Eventr
  2. 2. NodeJS <ul><li>Цель проекта: </li></ul>«Предоставить естественную неблокирующую , событийно-ориентированную инфраструктуру для написания программ с высокой конкурентностью» (с) Ryan Dahl « to provide a purely evented, non-blocking infrastructure to script highly concurrent programs »
  3. 3. NodeJS <ul><li>NodeJS – серверная JavaScript платформа </li></ul><ul><ul><li>Использует Google V 8 (Chromium: Google Chrome, Chrome OS, etc.) </li></ul></ul><ul><ul><li>Превращает V8 в мощную машину для серверных приложений </li></ul></ul><ul><ul><li>Сливается в гармонии с философией JavaScript </li></ul></ul><ul><ul><li>Молодой, но живой </li></ul></ul><ul><li>Event loop - неблокирующий ввод/вывод </li></ul><ul><ul><li>В се выполняется параллельно, кроме вашего кода </li></ul></ul>
  4. 4. Для чего подходит NodeJS <ul><li>Много I/O + большая конкурентность </li></ul><ul><ul><li>RIA — «богатые» приложения </li></ul></ul><ul><ul><li>API </li></ul></ul><ul><ul><li>Proxy </li></ul></ul><ul><li>Realtime </li></ul><ul><ul><li>Чаты </li></ul></ul><ul><ul><li>Онлайн игры </li></ul></ul><ul><ul><li>Трансляции </li></ul></ul><ul><ul><li>Publish/Subscribe </li></ul></ul>
  5. 5. Event loop <ul><li>Это цикл (libev) </li></ul><ul><li>Это один процесс, один поток </li></ul><ul><li>Выполняет одну задачу на один момент времени </li></ul><ul><li>Ожидает события параллельно (libeio, pooled threads) </li></ul><ul><li>В каждой итерации последовательно запускает функции-колбэки из трех разных очередей: </li></ul><ul><ul><li>nextTick функции </li></ul></ul><ul><ul><li>Таймеры ( setTimeout, setInterval) </li></ul></ul><ul><ul><li>Сигналы ввода/вывода ( libeio) </li></ul></ul><ul><li>Завершает работу, если все очереди пусты </li></ul>
  6. 6. Время <ul><li>CPU – процессорное время </li></ul><ul><ul><li>Интерпретация кода </li></ul></ul><ul><ul><li>Бизнес-логика приложения, алгоритмы </li></ul></ul><ul><ul><li>Рендеринг шаблонов </li></ul></ul><ul><li>I/O – время ввода/вывода </li></ul><ul><ul><li>Запросы в базу данных ( network) </li></ul></ul><ul><ul><li>Чтение файлов </li></ul></ul><ul><ul><li>Чтение кэша </li></ul></ul>I/O CPU
  7. 7. <ul><li><?php </li></ul><ul><li>$user = $db->query('SELECT * FROM users WHERE id=1'); // I/O - 70ms </li></ul><ul><li>$html = renderUser($user); // CPU - 30ms </li></ul>Упрощенный пример сценария веб-приложения На самом деле, у нас много I/O и много логики
  8. 8. <ul><li><?php </li></ul><ul><li>$user = $db->query('SELECT * FROM users WHERE id=1'); // I/O - 70ms </li></ul><ul><li>$html = renderUser($user); // CPU - 30ms </li></ul>CPU 30% I/O 70%
  9. 9. <ul><li><?php </li></ul><ul><li>$user = $db->query('SELECT * FROM users WHERE id=1'); // I/O - 70ms </li></ul><ul><li>$html = renderUser($user); // CPU - 30ms </li></ul>I/O CPU занято монолит А что если...
  10. 10. Blocking I/O callback I/O I/O CPU CPU занято свободно Event Loop монолит А что если во время ожидания I/O заниматься друмиги полезными делами?
  11. 11. I/O Event loop Примерно так выглядит более реальный запрос: CPU+I/O
  12. 12. I/O CPU callback I/O CPU Event loop Примерно так выглядит более реальный запрос:
  13. 13. Event loop Примерно так выглядит более реальный запрос: I/O CPU Свободно для других задач callback I/O CPU
  14. 14. Event Loop mysql.query(‘SELECT count(*) FROM users’, function(err, count) { console.log(‘There are %d users in db’, count); }) console.log(‘Hello, ’); Отправка запроса в БД
  15. 15. Event Loop mysql.query(‘SELECT count(*) FROM users’, function(err, count) { console.log(‘There are %d users in db’, count); }) console.log(‘Hello, ’); Hello , Ожидание ответа БД...
  16. 16. Event Loop mysql.query(‘SELECT count(*) FROM users’, function(err, count) { console.log(‘There are %d users in db’, count); }) console.log(‘Hello, ’); Hello, There are 10231512 users in db Пришел ответ из БД
  17. 17. <ul><li><?php </li></ul><ul><li>$user = $db->query('SELECT * FROM users WHERE id=1'); // I/O - 70ms </li></ul><ul><li>$html = renderUser($user); // CPU - 30ms </li></ul>db.query('SELECT * FROM users WHERE id=1’, function(err, user) { // I/O 70ms var html = renderUser(user); // CPU – 30ms })
  18. 18. <ul><li><?php </li></ul><ul><li>$user = $db->query('SELECT * FROM users WHERE id=1'); // I/O - 70ms </li></ul><ul><li>$html = renderUser($user); // CPU - 30ms </li></ul>db.query('SELECT * FROM users WHERE id=1’, function(err, user) { // I/O 70ms var html = renderUser(user); // CPU – 30ms } ) CPU 30% I/O 70%
  19. 19. Первый запрос Blocking I/O, 1 процесс
  20. 20. Второй запрос, после 10 ms ожидает выполнения первого Blocking I/O, 1 процесс
  21. 21. Третий запрос, после 50 ms ожидает выполнения первого и второго Blocking I/O, 1 процесс
  22. 22. Blocking I/O, 1 процесс Event loop, 1 процесс
  23. 23. Blocking I/O, 1 процесс Event loop, 1 процесс Время: 0 ms Пришел первый запрос, Запрашиваем I/O, освобождаемся , Ждем других запросов
  24. 24. Blocking I/O, 1 процесс Event loop, 1 процесс Время: 10 ms Пришел второй запрос, Запрашиваем I/O, освобождаемся , Ждем других запросов
  25. 25. Blocking I/O, 1 процесс Event loop, 1 процесс Время: 50 ms Пришел третий запрос, Запрашиваем I/O, освобождаемся , Ждем других запросов
  26. 26. Blocking I/O, 1 процесс Event loop, 1 процесс Время: 70 ms Пришел ответ на I/O первого запроса , запускаем callback 1
  27. 27. Blocking I/O, 1 процесс Event loop, 1 процесс Время: 80 ms Пришел ответ на I/O второго запроса, callback 2 ожидает своей очереди
  28. 28. Blocking I/O, 1 процесс Event loop, 1 процесс Время: 1 0 0 ms с allback 1 завершился, запускаем callback 2
  29. 29. Blocking I/O, 1 процесс Event loop, 1 процесс Время: 12 0 ms Пришел ответ на I/O третьего запроса, callback 3 ожидает своей очереди
  30. 30. Blocking I/O, 1 процесс Event loop, 1 процесс Время: 130 ms с allback 2 завершился, запускаем callback 3
  31. 31. Blocking I/O, 1 процесс Event loop, 1 процесс Время: 160 ms callback 3 завершился Ждем других запросов
  32. 32. Время CPU vs I/O RIA трэнд
  33. 33. Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_modules / </li></ul><ul><ul><li>express </li></ul></ul><ul><ul><li>sync </li></ul></ul><ul><ul><li>narrow </li></ul></ul>
  34. 34. Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_modules / </li></ul><ul><ul><li>express </li></ul></ul><ul><ul><li>sync </li></ul></ul><ul><ul><li>narrow </li></ul></ul>require.paths.unshift(‘./library’) var MyModule = require(‘my_module’) var Sync = require(‘sync’)
  35. 35. Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_modules / </li></ul><ul><ul><li>express </li></ul></ul><ul><ul><li>sync </li></ul></ul><ul><ul><li>narrow </li></ul></ul>var MyModule = function() { // … } module.exports = MyModule
  36. 36. Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_modules / </li></ul><ul><ul><li>express </li></ul></ul><ul><ul><li>sync </li></ul></ul><ul><ul><li>narrow </li></ul></ul>require.paths.unshift(‘./library’) var MyModule = require(‘my_module’) var Sync = require(‘sync’) console.log(‘my module: ‘, MyModule); +
  37. 37. Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_modules / </li></ul><ul><ul><li>express </li></ul></ul><ul><ul><li>sync </li></ul></ul><ul><ul><li>narrow </li></ul></ul>$ node my_app.js my module: function (){}
  38. 38. Приложение <ul><li>my_app.js </li></ul><ul><li>library / </li></ul><ul><ul><li>my_module.js </li></ul></ul><ul><li>node_modules / </li></ul><ul><ul><li>express </li></ul></ul><ul><ul><li>sync </li></ul></ul><ul><ul><li>narrow </li></ul></ul><ul><ul><li>mongoose </li></ul></ul>$ npm install mongoose
  39. 39. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>}).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>Подключаем HTTP модуль
  40. 40. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>}).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>Создаем HTTP сервер
  41. 41. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>}).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>«вешаем» сервер на 3080 порт
  42. 42. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>}).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>Сервер создан, выводим сообщение
  43. 43. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>} ).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>Функция будет вызвана индивидуально для каждого запроса
  44. 44. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>} ).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>Отправляем HTTP заголовок
  45. 45. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>} ).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>Отправляем HTTP тело и закрываем сокет
  46. 46. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>} ).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>$ node my_app.js
  47. 47. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>} ).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>$ node my_app.js Server running at http://127.0.0.1:3080/
  48. 48. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>} ).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>$ node my_app.js Server running at http://127.0.0.1:3080/ $ curl http://127.0.0.1:3080/
  49. 49. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer( function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello, Worldn’); </li></ul><ul><li>} ).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>$ node my_app.js Server running at http://127.0.0.1:3080/ $ curl http://127.0.0.1:3080/ Hello, World $
  50. 50. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>setTimeout(function(){ </li></ul><ul><li>res.end(‘World!n’); </li></ul><ul><li>}, 1000); </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.write(‘Hello,n’); </li></ul><ul><li>}).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>Hello сразу, World – через 1 сек + + + +
  51. 51. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>setTimeout(function(){ </li></ul><ul><li>res.end(‘World!n’); </li></ul><ul><li>}, 1000); </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.write(‘Hello,n’); </li></ul><ul><li>}).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>$ node my_app.js Server running at http://127.0.0.1:3080/ $ curl http://127.0.0.1:3080/ Hello,
  52. 52. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>setTimeout(function(){ </li></ul><ul><li>res.end(‘World!n’); </li></ul><ul><li>}, 1000); </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.write(‘Hello,n’); </li></ul><ul><li>}).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>$ node my_app.js Server running at http://127.0.0.1:3080/ $ curl http://127.0.0.1:3080/ Hello, World! $ Через секунду
  53. 53. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>var i = 0; </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘i = ’ + i + ‘n’); </li></ul><ul><li>i++; </li></ul><ul><li>}).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>Итератор, общий для всех запросов – javascript замыкание ( closure)
  54. 54. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>var i = 0; </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘i = ’ + i + ‘n’); </li></ul><ul><li>i++; </li></ul><ul><li>}).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>$ node my_app.js Server running at http://127.0.0.1:3080/ $ curl http://127.0.0.1:3080/ i = 0 $
  55. 55. HTTP <ul><li>var http = require(‘http’); </li></ul><ul><li>var i = 0; </li></ul><ul><li>http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘i = ’ + i + ‘n’); </li></ul><ul><li>i++; </li></ul><ul><li>}).listen(3080) </li></ul><ul><li>console.log(‘Server running at http://127.0.0.1:3080/’); </li></ul>$ node my_app.js Server running at http://127.0.0.1:3080/ $ curl http://127.0.0.1:3080/ i = 0 $ curl http://127.0.0.1:3080/ i = 1 $
  56. 56. Callback-driven парадигма <ul><li>Ломает мозг </li></ul><ul><li>Синтаксический шум </li></ul><ul><li>С ложно выполнить ряд действий в определенной последовательности </li></ul><ul><li>Необходимость вручную «пробрасывать» ошибки </li></ul><ul><li>Бесконечная индентация – aka «спагетти код» </li></ul>
  57. 57. Callback-driven парадигма function asyncFunction ( arg1, arg2, argN, callback ) { } Неблокирующая функция принимает callback последним аргументом
  58. 58. Callback-driven парадигма function asyncFunction ( arg1, arg2, argN, callback ) { } function callback ( err , result1, result2, resultN) { } Неблокирующая функция принимает callback последним аргументом Callback принимает ошибку первым аргументом, остальные – результат
  59. 59. Callback-driven парадигма function sum(a, b) { if (a > b) { throw new Error('a cannot be greater than b'); } return a + b; }
  60. 60. Callback-driven парадигма function sum(a, b) { if (a > b) { throw new Error('a cannot be greater than b'); } return a + b; } f unction asyncS um(a, b, callback ) { if (a > b) { return callback(new Error('a cannot be greater than b')); } callback(null, a + b); } + + +
  61. 61. Callback-driven парадигма function sum(a, b) { if (a > b) { throw new Error('a cannot be greater than b'); } return a + b; } f unction asyncS um(a, b, callback ) { if (a > b) { return callback(new Error('a cannot be greater than b')); } callback(null, a + b); } + + +
  62. 62. Callback-driven парадигма try { var result = sum(2, 3); console.log('result = %d', result); } catch (err) { console.error(err); }
  63. 63. Callback-driven парадигма try { var result = sum(2, 3); console.log('result = %d', result); } catch (err) { console.error(err); } asyncS um(2, 3, function(err, result){ if (err) return console.error(err); console.log('result = %d', result); }) + + +
  64. 64. Callback-driven парадигма function getUser(id, callback) { }
  65. 65. Callback-driven парадигма function getUser(id, callback) { } getUser(1234, function(err, user) { if (err) return console.error(err); console.log(‘user: ’, user); })
  66. 66. Callback-driven парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) return callback(err); }) } + + +
  67. 67. Callback-driven парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) return callback(err); dbConnect(config.host, function(err, db){ if (err) return callback(err); }) }) } + + +
  68. 68. Callback-driven парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) return callback(err); dbConnect(config.host, function(err, db){ if (err) return callback(err); db.getUser(id, function(err, user){ if (err) return callback(err); callback(null, user); }) }) }) } + + + +
  69. 69. Callback-driven парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) return callback(err); afterReadConfig(id, config, callback); }) } function afterReadConfig(id, config, callback) { dbConnect(config.host, function(err, db){ if (err) return callback(err); db.getUser(id, function(err, user){ … }) } + + + + + + +
  70. 70. Callback-driven парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) return callback(err); afterReadConfig(id, config, callback); }) } function afterReadConfig(id, config, callback) { dbConnect(config.host, function(err, db){ if (err) return callback(err); afterDbConnect(id, db, callback); }) } function afterDbConnect(id, db, callback) … + +
  71. 71. Callback-driven парадигма Error: User not found at afterDbConnect (/path/to/script.js:24:14) at /path/to/script.js:20:9 at dbConnect (/path/to/script.js:7:5) at afterReadConfig (/path/to/script.js:18:5) at /path/to/script.js:13:9 at readConfig (/path/to/script.js:3:5) at getUser (/path/to/script.js:11:5) at Object.<anonymous> (/path/to/script.js:28:1) at Module._compile (module.js:404:26) at Object..js (module.js:410:10)
  72. 72. Callback-driven парадигма Error: User not found at afterDbConnect (/path/to/script.js:24:14) at /path/to/script.js:20:9 at dbConnect (/path/to/script.js:7:5) at afterReadConfig (/path/to/script.js:18:5) at /path/to/script.js:13:9 at readConfig (/path/to/script.js:3:5) at getUser (/path/to/script.js:11:5) at Object.<anonymous> (/path/to/script.js:28:1) at Module._compile (module.js:404:26) at Object..js (module.js:410:10)
  73. 73. Callback-driven парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) return callback(err); afterReadConfig(id, config, callback); }) } function afterReadConfig(id, config, callback) { dbConnect(config.host, function(err, db){ if (err) return callback(err); afterDbConnect(id, db, callback); }) } function afterDbConnect(id, db, callback) … Синтаксический шум – плата за Evented I/O
  74. 74. Callback-driven парадигма function getUser(id, callback) { readConfig(‘config.json’, function(err, config){ if (err) return callback(err); afterReadConfig(id, config, callback); }) } function afterReadConfig(id, config, callback) { dbConnect(config.host, function(err, db){ if (err) return callback(err); afterDbConnect(id, db, callback); }) } function afterDbConnect(id, db, callback) … Синтаксический шум – плата за Evented I/O PROFIT PROFIT
  75. 75. node-sync Function.prototype.sync = function(context, arguments…) <ul><li>Использует сопрограммы (coroutines ) с++ </li></ul><ul><li>Основан на node-fibers </li></ul><ul><li>Позволяет писать синхронно на nodejs </li></ul>https://github.com/ 0 ctave/node-sync https://github.com/ laverdet /node-fibers
  76. 76. var Sync = require(‘sync’); function getUser(id, callback) { Sync(function(){ var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.sync(null, config.host); var user = db.getUser.sync(db, id); return user; }, callback) } Запускаем новое «волокно» ( Fiber) node-sync
  77. 77. var Sync = require(‘sync’); function getUser(id, callback) { Sync(function(){ var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.sync(null, config.host); var user = db.getUser.sync(db, id); return user; }, callback) } «Волокно» вернет значение или ошибку в callback node-sync
  78. 78. var Sync = require(‘sync’); function getUser(id, callback) { Sync(function(){ var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.sync(null, config.host); var user = db.getUser.sync(db, id); return user; }, callback) } Функция readConfig вызывается синхронно и возвращает значение node-sync
  79. 79. var Sync = require(‘sync’); function getUser(id) { var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.sync(null, config.host); var user = db.getUser.sync(db, id); return user; }.async() То же самое, только проще (коллбэка нет) node-sync
  80. 80. var Sync = require(‘sync’); function getUser(id) { var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.sync(null, config.host); var user = db.getUser.sync(db, id); return user; }.async() node-sync getUser(1234, function(err, user) { if (err) return console.error(err); console.log(‘user: ’, user); })
  81. 81. var Sync = require(‘sync’); function getUser(id) { var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.sync(null, config.host); throw new Error(‘something went wrong’); return user; }.async() node-sync getUser(1234, function(err, user) { if (err) return console.error(err); console.log(‘user: ’, user); })
  82. 82. var Sync = require(‘sync’); function getUser(id) { var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.sync(null, config.host); var user = db.getUser.future(db, id); var friends = db.getUserFriends.future(db, id); return { user : user.result, friends : friends.result }; }.async() node-sync getUser и getUserFriends выполняются параллельно
  83. 83. var Sync = require(‘sync’); function getUser(id) { var config = readConfig.sync(null, ‘config.json’); var db = dbConnect.sync(null, config.host); var user = db.getUser.future(db, id); db.getUserFriends(id, friends = new Sync.Future()); return { user : user.result, friends : friends.result }; }.async() node-sync другой способ получения «тикета» future
  84. 84. Callback-driven парадигма $pages = $db->fetchRows(‘SELECT * FROM pages’); foreach ($pages as $page) { $contents = fetchUrl($page->url); }
  85. 85. Callback-driven парадигма $pages = $db->fetchRows(‘SELECT * FROM pages’); foreach ($pages as $page) { $contents = fetchUrl($page->url); } OK
  86. 86. Callback-driven парадигма $pages = $db->fetchRows(‘SELECT * FROM pages’); foreach ($pages as $page) { $contents = fetchUrl($page->url); } db.fetchRows(‘SELECT * FROM pages’, function(err, pages){ pages.forEach(function(page){ fetchUrl(page.url, function(err, contents) { }) }) }); OK
  87. 87. Callback-driven парадигма $pages = $db->fetchRows(‘SELECT * FROM pages’); foreach ($pages as $page) { $contents = fetchUrl($page->url); } db.fetchRows(‘SELECT * FROM pages’, function(err, pages){ pages.forEach(function(page){ fetchUrl(page.url, function(err, contents) { }) }) }); x 100,000 OK
  88. 88. Callback-driven парадигма db.fetchRows(‘SELECT * FROM pages’, function(err, pages){ var narrow = new Narrow(10, function(page, callback){ fetchUrl(page.url, function(err, contents) { }) }) narrow.pushAll(pages); }); + + + https://github.com/ 0 ctave/node-narrow
  89. 89. Callback-driven парадигма db.fetchRows(‘SELECT * FROM pages’, function(err, pages){ var narrow = new Narrow(10, function(page, callback){ fetchUrl(page.url, function(err, contents) { }) }) narrow.pushAll(pages); }); x10 - OK + + + x 100,000 - OK https://github.com/ 0 ctave/node-narrow
  90. 90. Callback - driven решения? <ul><li>node-sync - использует сопрограммы (coroutines ) </li></ul><ul><li>streamline.js – транслирует код </li></ul><ul><li>node-async – целый инструментарий для асинхронного программирования </li></ul><ul><li>Ваша собственная flow-control библиотека :) </li></ul>https://github.com/ 0 ctave/node-sync https://github.com/ Sage/streamlinejs https://github.com/caolan/async https://github.com/joyent/node/wiki/modules#async-flow http://www.scribd.com/doc/40366684/Nodejs-Controlling-Flow
  91. 91. Масштабирование Nodejs – is just node (c) Ryan Dahl
  92. 92. Масштабирование Nodejs – is just node (c) Ryan Dahl 1 ядро CPU = 1 nodejs процесс
  93. 93. Масштабирование <ul><li>node-cluster </li></ul><ul><ul><li>Расширяемый </li></ul></ul><ul><ul><li>Поддержка POSIX сигналов </li></ul></ul><ul><ul><li>«Горячая» перезагрузка ( zero-downtime) </li></ul></ul><ul><ul><li>«Аккуратное» завершение (graceful shutdown) </li></ul></ul><ul><ul><li>Автоматом перезапускает мертвые процессы </li></ul></ul><ul><ul><li>Не оставляет «зомби» </li></ul></ul><ul><ul><li>Автоматом определяет соличество ядер CPU </li></ul></ul><ul><ul><li>Поддержка REPL </li></ul></ul><ul><ul><li>Статистика </li></ul></ul><ul><ul><li>PID файлы </li></ul></ul><ul><ul><li>Логи </li></ul></ul>https://github.com/LearnBoost/cluster
  94. 94. HTTP Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server = http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello from ‘ + process.pid + ‘n’); </li></ul><ul><li>}); </li></ul><ul><li>cluster(server).listen(3080); </li></ul><ul><li>console.log(‘Server at http://127.0.0.1:3080/ (pid: %d)’, process.pid); </li></ul>Подключаем модуль cluster https://github.com/LearnBoost/cluster
  95. 95. HTTP Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server = http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello from ‘ + process.pid + ‘n’); </li></ul><ul><li>}); </li></ul><ul><li>cluster(server).listen(3080); </li></ul><ul><li>console.log(‘Server at http://127.0.0.1:3080/ (pid: %d)’, process.pid); </li></ul>Оборачиваем http сервер в кластер и «вешаем» на 3080 порт https://github.com/LearnBoost/cluster
  96. 96. HTTP Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server = http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello from ‘ + process.pid + ‘n’); </li></ul><ul><li>}); </li></ul><ul><li>cluster(server).listen(3080); </li></ul><ul><li>console.log(‘Server at http://127.0.0.1:3080/ (pid: %d)’, process.pid); </li></ul>Дополнительно выводим PID https://github.com/LearnBoost/cluster
  97. 97. HTTP Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server = http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello from ‘ + process.pid + ‘n’); </li></ul><ul><li>}); </li></ul><ul><li>cluster(server).listen(3080); </li></ul><ul><li>console.log(‘Server at http://127.0.0.1:3080/ (pid: %d)’, process.pid); </li></ul>https://github.com/LearnBoost/cluster $ node my_app.js Server at http://127.0.0.1:3080/ (pid: 9254) Server at http://127.0.0.1:3080/ (pid: 9255) Server at http://127.0.0.1:3080/ (pid: 9256)
  98. 98. HTTP Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server = http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello from ‘ + process.pid + ‘n’); </li></ul><ul><li>}); </li></ul><ul><li>cluster(server).listen(3080); </li></ul><ul><li>console.log(‘Server at http://127.0.0.1:3080/ (pid: %d)’, process.pid); </li></ul>https://github.com/LearnBoost/cluster $ node my_app.js Server at http://127.0.0.1:3080/ (pid: 9254) Server at http://127.0.0.1:3080/ (pid: 9255) Server at http://127.0.0.1:3080/ (pid: 9256) $ curl http://127.0.0.1:3080/ Hello from 9255 $
  99. 99. HTTP Cluster <ul><li>var http = require(‘http’), cluster = require(‘cluster’); </li></ul><ul><li>var server = http.createServer(function(req, res){ </li></ul><ul><li>res.writeHead(200, { ‘Content-Type’ : ‘text/plain’ }); </li></ul><ul><li>res.end(‘Hello from ‘ + process.pid + ‘n’); </li></ul><ul><li>}); </li></ul><ul><li>cluster(server).listen(3080); </li></ul><ul><li>console.log(‘Server at http://127.0.0.1:3080/ (pid: %d)’, process.pid); </li></ul>https://github.com/LearnBoost/cluster $ node my_app.js Server at http://127.0.0.1:3080/ (pid: 9254) Server at http://127.0.0.1:3080/ (pid: 9255) Server at http://127.0.0.1:3080/ (pid: 9256) $ curl http://127.0.0.1:3080/ Hello from 9255 $ curl http://127.0.0.1:3080/ Hello from 925 6 $
  100. 100. NodeJS + Много I/O Много Запросов + Event Loop = PROFIT
  101. 101. Юра Богданов https://github.com/ 0 ctave Github: http://twitter.com/ yuriybogdanov Twitter: http://about.me/ bogdanov About.me: [email_address] Email: http://linkedin.com/ in/yuriybogdanov LinkedIn: Спасибо за внимание .

×