My Node.js workshop from Sela's Developer Conference 2015.
In the Workshop we covered The basics Node.js api's and the express web application framework.
4. What is Node.js
A JavaScript runtime that is designed for
asynchronous IO operations
Very lightweight and fast
Being used by a growing number of companies:
5. The Node.js ecosystem
Node.js has a rapidly growing ecosystem:
Web frameworks:
Express
Socket.io
Database support
Sql Databases
NoSql Databases
Hosting and Cloud environments
IIS, Azure
Heroku
Joyent
6. Synchronous server operations
// GET api/countries
public string Get()
{
var client = WebRequest.Create("http://.../");
var response = client.GetResponse();
var stream = response.GetResponseStream();
var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
Blocking I/O operation
7. The Cost of I/O
I/O Operations are expensive.
I/O Source CPU Cycles
L1 – Cache 3
L2 – Cache 14
RAM 250
Disk 41,000,000
Network 240,000,000
8. Handling I/O
Waiting for I/O operations to complete is one of
the most common performance bottlenecks.
There are several common solutions to handle
it:
Synchronous
Pros: simple.
Cons: blocking, can hold up other requests.
Fork a new process
Pros: efficient, not holding up other requests.
Cons: does not scale, ~100 connections=~100 processes .
9. Handling I/O
Threads:
Pros:
efficient, not holding up other requests but more
lightweight then executing another process
Cons:
memory-expensive - ~1MB per thread, complicated, need
to worry about controlling access and shared resources.
Traditional web-servers (IIS, Apache) today use
an optimized thread-per-connection model that
uses thread pools.
10. Handling I/O in Node.js
Node.js runs your code on a single thread.
All I/O operations are asynchronous and Non-
Blocking
Internally threads and processes are used but not
explicitly exposed to your code.
When an I/O operation completes, an event is
triggered and the result is passed to a callback
function.
11. Why Node.js
Lightweight and efficient
using non-blocking I/O keeps memory consumption
stable by reducing the number of threads.
Less context switching overhead.
Concurrency
using non-blocking I/O keeps the main thread
responsive and allowing it support tens of thousands
of concurrent connections.
One Language
allows reuse of resources between the client and
server.
14. Node.js Event loop
I/O operations are evented and external events
are handled by Node’s Event loop.
Javascript functions are passed to a queue and
invoked when the return value from their
current I/O calls is available.
I/O Callbacks are invoked synchronously by the
order they returned.
17. Node.js Usage
Running CPU intensive tasks (e.g. long running
loops) on Node.js’s main thread should be
avoided as it will block handling other requests
to the server.
Running CPU intensive tasks can be scaled out
to multiple node processes.
Node.js can run a managed cluster of multiple
processes to scale out an entire application.
18. The Node.js process
Unlike client-side JavaScript Node.js does not
run inside a browser window.
There are no window or document global
objects
The Node process provides the runtime for
node programs
19. Node.js process architecture
Node.exe
V8
CommonJS – Module loader
JavaScript Application
libuv
OS
Core Javascript modules for file
system, network, http, etc…
Responsible for loading modules
and manage dependencies.
Using CommonJS’s module
definition.
Multi-platform library written in C
that handles all async I/O
operations.
Google’s Javascript Engine.
Compiles the Javascript code to
native machine code.
20. The process global object
The process global object provides an API for
interacting with the process
Access command-line arguments
Get the execution path, current platform, node.js
version
Environment variables
Accessing standard input/output
23. File System
Node.js provides the fs module for file system
operations:
Readingwriting files
Getting file metadata
Reading directories
Creating a file watcher
Most fs functions have synchronous APIs
24. Reading Directories
var fs = require('fs');
// this method reads the content of a directory
fs.readdir(process.argv[2], function(err,files){
files.forEach(function(file){
//Do something with file…
});
});
26. Reading files
The fs module prvides different methods for
reading file content:
readFileSync reading the whole file synchronously
readFile reading the whole file asynchronously
createReadStream provides a stream based API for
reading files
27. var fs = require('fs');
//Async
fs.readFile(process.argv[2],'utf-8', function (err, data) {
if (err) throw err;
console.log(data)
});
//Read file sync
var f = fs.readFileSync(process.argv[2],'utf-8');
console.log(f);
Reading Files
29. Streams
Just like other frameworks Node.js use streams
as an abstraction for reading/writing data.
Just like most IO in Node.js, streams provide an
event base API using the on method
close, open
data
error
When using streams, data is read in chunks and
doesn’t block the main thread for the entire
time the data is buffered into memory.
30. Streams (cont.)
var fs = require('fs');
var strm = fs.createReadStream(process.argv[2]);
strm.setEncoding('utf8');
strm.on('data', function(data) {
console.log('read from strm');
});
strm.on('end', function(){
console.log('ended strm')
})
31. The pipe method allows you to connect a
readable stream as the destination of a
writeable stream
var fs = require("fs");
// Read File
fs.createReadStream("input/people.json")
// Write File
.pipe(fs.createWriteStream("output/people.json"));
Stream.pipe
35. Building HTTP servers
Node.js was originally designed as a platform
for building web servers.
Most Web applications are I/O Bound
~90% of a request’s processing time is spent on
waiting for I/O to complete.
Node.js async I/O mechanism provides node
with high concurrency and a low memory
footprint.
36. Building HTTP servers (cont.)
Node.js is designed to be scaled out to multiple
processes and machines which makes it ideal
for cloud hosting.
The http module provides basic functionality
for handling HTTP (client and server)
Additional frameworks like Express and Restify
provide higher level abstractions (like MVC)
37. var http = require('http');
http.createServer(function(req,res){
var response = 'Hello World';
res.writeHead(200,
{
'Content-Type': 'text/plain',
'Content-Length': response.length
});
res.write(response);
res.end();
}).listen(3000);
Node Http Server
39. The http.Server class
The http.createServer() method is used to
create a server.
It returns an instance of the http.Server object.
The http.Server provides a set of events
request – fires on every incoming request.
Connection -fires on every new tcp connection.
Upgrade - fires on every incoming upgrade request.
41. Receiving data
HTTP allows server applications to receive data:
Using the request URI
Message body
Use the url and querystring modules for
parsing URLs and query strings.
Message body can contain any format
Being a JavaScript runtime, Node.js process JSON
natively
Other formats are supported through npm packages.
42. var http = require('http');
var url = require('url') ;
http.createServer(function (req, res) {
var queryObject = url.parse(req.url,true).query;
console.log(queryObject);
res.writeHead(200);
res.end('Feel free to add query parameters to the end of the
url');
}).listen(8080);
Parsing URL and Querystring
45. Chunked transfer encoding
HTTP 1.1 introduced Chunked transfer encoding
that allows messages to be sent in chunks.
The Content-Length header is removed and a
Transfer-Encoding:chunked header is added to
the response.
HTTP can send messages in chunks
Write data in small chunks keeping a small memory
footprint
Freeing node’s single thread to serve more requests
46. var http = require('http');
var handleRequests = function(req,res){
// creating an outgoing HTTP request
var req2 = http.request(options, responseCallback = function(response) {
res.writeHead(200, {'content-type': 'text/xml', 'Content-
Encoding':'gzip'})
response.on('data', function (chunk) {
res.write(chunk);
});
response.on('end', function(){
res.end();
});
});
req2.end();
};
http.createServer(handleRequests).listen(3000);
Chunked transfer encoding
50. CommonJS Modules
Node.js uses CommonJS modules for
structuring code.
Modules are defined in separate .js files
To consume a module use the require
function
51. Modules and Scopes
Modules provide a simple mechanism for
creating scopes in JavaScript
Members defined inside a module are not
accessible outside
To expose a member use the exports object
This allow CommonJS to simplify dependency
resolution
53. The Global object
Unlike browsers the top-level scope in Node.js
is the module not global
To expose objects globally (across modules)
you can add them to the global object
55. Node Package Manager (NPM)
The Node Package Manager (NPM) provides a
management mechanism for modules:
Download and install
Version management
Deployment
57. Managing Dependencies
NPM packages are managed in a file called
package.json
package.json schema define fields like:
name, description
Version
Dependencies
Dependencies are being resolved during NPM
install
60. Managing Dependencies
NPM packages are installed inside a folder
named node_modules
The folder is created inside the path where the
“npm install …” was executed.
When a npm module is required node will look
it up inside the node_modules folder of the
current path.
If the module is not found it is recursively searched
up the folder tree.
62. The EventEmitter
Most of Node.js's APIs are event based
The events module provides the event emitter
object for emitting events.
Events are fired through the emit method and
can be watched using the on method.
66. Introduction to Express
Node.js http module provides bare-bones HTTP
server functionality
Building a modern web application server
would require implementing many common
features such as:
Routing
Session Management
Cookies & Requests Parsers
Request Logging
67. Introduction to Express
Express is a web application framework inspired
by Sinatra.
Express middleware provides an expendable
Http pipeline on top of Node.js's httpServer
An Express application is essentially a series of
middleware calls
A middleware is simply a function with access to
the request object, response object and a
callback to next middleware in line.
68. Express is available through npm
$ npm install express --save
Express provides a generator tool to quickly
create an application skeleton.
$ npm install express-generator –g
//run
$ express -h
Express Installation
70. Routing is one of the pillars of Express
To create a route use the app.verb convention
// respond with "Hello World!" on the homepage
app.get('/', function (req, res) {
res.send('Hello World!');
})
// accept POST request on the homepage
app.post('/', function (req, res) {
res.send('Got a POST request');
})
// accept PUT request at /user
app.put('/user', function (req, res) {
res.send('Got a PUT request at /user');
})
Routing
71. Routers
An Express application might have a large
number of routes defined.
Maintaining All of them in a single file can be a pain.
Routers helps you keep your routes clean,
organized and modular.
Routers are defined in a separate node modules
and used as middlewares.
72. A router is an isolated instance of middlewares
and routes.
The router can have middleware and http VERB
routes added just like an application.
var router = express.Router([options]);
router.get('/events', function(req, res, next) {
// .. some logic here .. like any other middleware // ..
});
Routers (cont.)
74. Routing and Parameters
Express support parameters as part of the URI
Declare a parameter in the URI by using a “:” in
front of it
Access query-string parameters using req.query
Use regular expressions
To set a parameter as optional add a “?” suffix.
77. Express application settings can be set using
app.set() and retrieved using app.get()
You can also set middleware functions using
app.use().
// this middleware will be executed for every request to the
app
app.use(function (req, res, next) {
console.log('Time: %d', Date.now());
next();
})
Configuring Express
78. Views are template based UI mechanism
Express support many view-engines including:
Jade
JSHtml
EJS
View engines are defined by setting the ‘view-
engine’ variable
app.set('view engine', 'jade');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
Views
79. Jade
Jade is Express default view-engine
It is based on Haml it provide a clean syntax for
generating HTML
Tab based
Full support for HTML
82. Jade fully support JavaScript using the script
element:
Linking to external JS files
Embedding in-line JavaScript
To setup static content serving in Express use
the built-in static middleware.
app.use(express.static(__dirname+'/public'));
// multiple static folders can be defined.
Mixing up JavaSript & Jade
84. Blocks
In most applications, some UI components are
used throughout the application
Blocks provide a way to provide a common
layout that is shared among views
91. Functionality to Express apps are added via
third-party middleware installed through npm.
$ npm install cookie-parser
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
// load the cookie parsing middleware
app.use(cookieParser());
Express Middlewares
92. Common Express Middlewares
Express 4.0 Name
body-parser
compression
cookie-session
morgan
cookie-parser
express-session
static-favicon
response-time
errorhandler
method-override
connect-timeout
vhost
csurf
93. var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/json
app.use(bodyParser.json())
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:n')
res.end(JSON.stringify(req.body, null, 2))
})
The body-parser middleware
94. var express = require('express')
var session = require('express-session')
var app = express()
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
app.use(function(req, res, next) {
var sess = req.session
if (sess.views) {
sess.views++
} else {
sess.views = 1
res.end('welcome to the session demo. refresh!')
}
})
Express-Session
97. Summary
Node.js is not just for building servers
It allows JavaScript to run outside of browsers
and perform asynchronous IO
It is asynchronous by nature
Node.js runs your code on a single thread.
Lightweight, fast and extremely cool.
nirn@sela.co.il | @noynir
Talk about yourself
Ask how many write server code? How many .net?
Something about your references are from the .net world
Anybody from bat-yam
Ask what is node.JS? Probably get an answer “Server side javascript”
Explain the exact definition, more to come on async io
Small memory footprint and fast because doesn’t sit on top of a framework, more to come…
All the big players are using this which makes node a safer bet because these companies are actively taking part in node development (Microsoft on the windows side…) and have interest in moving this technology forward.
In addition to companies node.js has a very active community
What is npm? Npm has ~150 packages, nuget ~37
What seems to be wrong in this code??
Client.getResponse is a blocking I/O Operation.
I/O Operation are costly and have impact on performance mostly because they take time and are blocking our code.
Take a look at the bottom 2 lines and see the Hugh difference.
The actual time depends on hardware.
So how does node.js handles IO?
Your code runs on a single thread, very important to be in our state of mind cause we can cause to be blocking.
What happens when we want to IO? -> async, non blocking.
Everything runs with events we give a callback function and once io completes the callback executes.
Internally it runs threads, but not the same threads we use, but kernel level threads run by the OS.
So why is this model good for us?-> Explain the restaurant analogy.
On large scales opening threads on each connection is not good enough.
Explain the basic node concepts:
Modules and how we import them using require
The use of callbacks
Explain why javascript?
So how does the async io is managed? -> event loops.
Node.js runs on events, every callback is inserted in to a queue, that check in a loop all the time
Once io completes the callback in the queue is marked completed and when node gets to it he will execute it.
Important!! callback are invokes sync.
Show 2_setTimeout add a for loop with 10000 iterations inside the first callback and show how it effects the execution of the second one
Run the 1_AsyncServer demo from the command line
Use the REPL and do some basic JavaScript
Run the 3_FileSystem – list.js demo from the command line
Run the 3_FileSystem demos
First -> Explain it is blocking node’s only thread
Second -> read-> readfilesync.js fileasync.js -> Not blocking but is performed in a serial manner
Third -> readstream.js -> explain streams
Run the 3_FileSystem demos pipes
Run the 1_AsyncServer demo from the command line
Use the REPL and do some basic JavaScript
Run the 1_AsyncServer demo from the command line
Use the REPL and do some basic JavaScript