SlideShare ist ein Scribd-Unternehmen logo
1 von 71
Downloaden Sie, um offline zu lesen
NODE.JS SCALABILITY TIPS
NODE.JS SCALABILITY TIPS
Luciano Mammino ( )
@loige
loige.link/node-adc
Vijayawada - 2021-12-13
1
@loige
Get the slides! πŸ‘‡
loige.link/node-adc
2
HELLO!
3
HELLO!
πŸ‘‹I'm LucianoΒ ( πŸ•πŸ )
3
HELLO!
πŸ‘‹I'm LucianoΒ ( πŸ•πŸ )
Senior Architect @ fourTheorem (Dublin )
3
HELLO!
πŸ‘‹I'm LucianoΒ ( πŸ•πŸ )
Senior Architect @ fourTheorem (Dublin )
nodejsdp.link
πŸ“”Co-Author of Node.js Design PatternsΒ  πŸ‘‰
3
HELLO!
πŸ‘‹I'm LucianoΒ ( πŸ•πŸ )
Senior Architect @ fourTheorem (Dublin )
nodejsdp.link
πŸ“”Co-Author of Node.js Design PatternsΒ  πŸ‘‰
Let's connect!
Β  (blog)
Β  (twitter)
Β  (twitch)
Β  (github)
loige.co
@loige
loige
lmammino
3
WE ARE BUSINESS FOCUSED TECHNOLOGISTS THAT DELIVER.
Β | Β |
Accelerated Serverless AI as a Service Platform Modernisation
We are hiring: do you want to ?
work with us
loige 4
"A service is said to be scalable if when we
increase the resources in a system, it
results in increased performance in a
manner proportional to resources added"
β€” Werner Vogels
@loige
5
πŸ›«
TIP 1.
ESTABLISH A BASELINE
@loige
6
/?data=ciaoπŸ‘‹
@loige
Site: Β - Code:
qrgen.lmammino.repl.co replit.com/@lmammino/QRGen 7
import { createServer } from 'http'
import QRCode from 'qrcode'
createServer(function handler (req, res) {
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
res.writeHead(200, { 'Content-Type': 'image/png' })
QRCode.toFileStream(res, data, { width: 300 })
}).listen(8080)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@loige
8
import { createServer } from 'http'
import QRCode from 'qrcode'
createServer(function handler (req, res) {
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
res.writeHead(200, { 'Content-Type': 'image/png' })
QRCode.toFileStream(res, data, { width: 300 })
}).listen(8080)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createServer } from 'http'
import QRCode from 'qrcode'
1
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
@loige
8
import { createServer } from 'http'
import QRCode from 'qrcode'
createServer(function handler (req, res) {
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
res.writeHead(200, { 'Content-Type': 'image/png' })
QRCode.toFileStream(res, data, { width: 300 })
}).listen(8080)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createServer } from 'http'
import QRCode from 'qrcode'
1
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
createServer(function handler (req, res) {
}).listen(8080)
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
18
@loige
8
import { createServer } from 'http'
import QRCode from 'qrcode'
createServer(function handler (req, res) {
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
res.writeHead(200, { 'Content-Type': 'image/png' })
QRCode.toFileStream(res, data, { width: 300 })
}).listen(8080)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createServer } from 'http'
import QRCode from 'qrcode'
1
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
createServer(function handler (req, res) {
}).listen(8080)
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
18
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
createServer(function handler (req, res) {
4
5
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
@loige
8
import { createServer } from 'http'
import QRCode from 'qrcode'
createServer(function handler (req, res) {
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
res.writeHead(200, { 'Content-Type': 'image/png' })
QRCode.toFileStream(res, data, { width: 300 })
}).listen(8080)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createServer } from 'http'
import QRCode from 'qrcode'
1
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
createServer(function handler (req, res) {
}).listen(8080)
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
18
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
createServer(function handler (req, res) {
4
5
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
7
8
9
10
11
12
13
14
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
@loige
8
import { createServer } from 'http'
import QRCode from 'qrcode'
createServer(function handler (req, res) {
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
res.writeHead(200, { 'Content-Type': 'image/png' })
QRCode.toFileStream(res, data, { width: 300 })
}).listen(8080)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createServer } from 'http'
import QRCode from 'qrcode'
1
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
createServer(function handler (req, res) {
}).listen(8080)
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
18
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
createServer(function handler (req, res) {
4
5
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
7
8
9
10
11
12
13
14
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
res.writeHead(200, { 'Content-Type': 'image/png' })
QRCode.toFileStream(res, data, { width: 300 })
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
16
17
}).listen(8080)
18
@loige
8
import { createServer } from 'http'
import QRCode from 'qrcode'
createServer(function handler (req, res) {
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
res.writeHead(200, { 'Content-Type': 'image/png' })
QRCode.toFileStream(res, data, { width: 300 })
}).listen(8080)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createServer } from 'http'
import QRCode from 'qrcode'
1
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
createServer(function handler (req, res) {
}).listen(8080)
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
18
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
createServer(function handler (req, res) {
4
5
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
7
8
9
10
11
12
13
14
15
res.writeHead(200, { 'Content-Type': 'image/png' })
16
QRCode.toFileStream(res, data, { width: 300 })
17
}).listen(8080)
18
res.writeHead(200, { 'Content-Type': 'image/png' })
QRCode.toFileStream(res, data, { width: 300 })
import { createServer } from 'http'
1
import QRCode from 'qrcode'
2
3
createServer(function handler (req, res) {
4
const url = new URL(req.url, 'http://localhost:8080')
5
const data = url.searchParams.get('data')
6
if (!data) {
7
res.writeHead(200, {'Content-Type': 'text/html'})
8
return res.end(`<html>
9
<body>
10
<p>To use this app you need to set the <code>data</code> querystrin
11
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
12
</body>
13
</html>`)
14
}
15
16
17
}).listen(8080)
18
import { createServer } from 'http'
import QRCode from 'qrcode'
createServer(function handler (req, res) {
const url = new URL(req.url, 'http://localhost:8080')
const data = url.searchParams.get('data')
if (!data) {
res.writeHead(200, {'Content-Type': 'text/html'})
return res.end(`<html>
<body>
<p>To use this app you need to set the <code>data</code> querystrin
<p>Try for example <a href="/?data=hello">/?data=hello</a></p>
</body>
</html>`)
}
res.writeHead(200, { 'Content-Type': 'image/png' })
QRCode.toFileStream(res, data, { width: 300 })
}).listen(8080)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@loige
8
autocannon -c 200 --on-port / -- node server.js
WRK
node server.js&
wrk -t8 -c200 -d10s http://localhost:8080/
@loige
9
autocannon -c 200 --on-port /?data=ciaoπŸ‘‹ -- node server.js
Running 10s test @ http://localhost:8080/?data=ciaoπŸ‘‹
200 connections
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stat β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ 99% β”‚ Avg β”‚ Stdev β”‚ Max β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Latency β”‚ 1899 ms β”‚ 1951 ms β”‚ 2053 ms β”‚ 2054 ms β”‚ 1964.92 ms β”‚ 99.9 ms β”‚ 3364.03 ms β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stat β”‚ 1% β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ Avg β”‚ Stdev β”‚ Min β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Req/Sec β”‚ 0 β”‚ 0 β”‚ 30 β”‚ 199 β”‚ 99.5 β”‚ 94.27 β”‚ 30 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Bytes/Sec β”‚ 0 B β”‚ 0 B β”‚ 50.7 kB β”‚ 336 kB β”‚ 168 kB β”‚ 159 kB β”‚ 50.7 kB β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Req/Bytes counts sampled once per second.
995 requests in 10.08s, 1.68 MB read
@loige
10
autocannon -c 200 --on-port /?data=ciaoπŸ‘‹ -- node server.js
Running 10s test @ http://localhost:8080/?data=ciaoπŸ‘‹
200 connections
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stat β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ 99% β”‚ Avg β”‚ Stdev β”‚ Max β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Latency β”‚ 1899 ms β”‚ 1951 ms β”‚ 2053 ms β”‚ 2054 ms β”‚ 1964.92 ms β”‚ 99.9 ms β”‚ 3364.03 ms β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stat β”‚ 1% β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ Avg β”‚ Stdev β”‚ Min β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Req/Sec β”‚ 0 β”‚ 0 β”‚ 30 β”‚ 199 β”‚ 99.5 β”‚ 94.27 β”‚ 30 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Bytes/Sec β”‚ 0 B β”‚ 0 B β”‚ 50.7 kB β”‚ 336 kB β”‚ 168 kB β”‚ 159 kB β”‚ 50.7 kB β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Req/Bytes counts sampled once per second.
995 requests in 10.08s, 1.68 MB read
@loige
10
β›…
TIP 1-BIS
ALSO, FIND OUT YOUR CEILING
@loige
11
import { createServer } from 'http'
createServer((req, res) => {
if (req.method === 'GET' && req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Hello Worldn')
} else {
res.statusCode = 404
res.end()
}
}).listen(8080)
1
2
3
4
5
6
7
8
9
10
11
@loige
12
import { createServer } from 'http'
createServer((req, res) => {
if (req.method === 'GET' && req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Hello Worldn')
} else {
res.statusCode = 404
res.end()
}
}).listen(8080)
1
2
3
4
5
6
7
8
9
10
11
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Hello Worldn')
import { createServer } from 'http'
1
2
createServer((req, res) => {
3
if (req.method === 'GET' && req.url === '/') {
4
5
6
} else {
7
res.statusCode = 404
8
res.end()
9
}
10
}).listen(8080)
11
@loige
12
autocannon -c 200 --on-port / -- node server.js
Running 10s test @ http://localhost:8080/
200 connections
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stat β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ 99% β”‚ Avg β”‚ Stdev β”‚ Max β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Latency β”‚ 3 ms β”‚ 5 ms β”‚ 11 ms β”‚ 14 ms β”‚ 5.51 ms β”‚ 2.71 ms β”‚ 80.63 ms β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stat β”‚ 1% β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ Avg β”‚ Stdev β”‚ Min β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Req/Sec β”‚ 21087 β”‚ 21087 β”‚ 34623 β”‚ 35487 β”‚ 33258.4 β”‚ 4107.01 β”‚ 21077 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Bytes/Sec β”‚ 3.29 MB β”‚ 3.29 MB β”‚ 5.4 MB β”‚ 5.54 MB β”‚ 5.19 MB β”‚ 641 kB β”‚ 3.29 MB β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Req/Bytes counts sampled once per second.
333k requests in 10.1s, 51.9 MB read
@loige
13
autocannon -c 200 --on-port / -- node server.js
Running 10s test @ http://localhost:8080/
200 connections
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stat β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ 99% β”‚ Avg β”‚ Stdev β”‚ Max β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Latency β”‚ 3 ms β”‚ 5 ms β”‚ 11 ms β”‚ 14 ms β”‚ 5.51 ms β”‚ 2.71 ms β”‚ 80.63 ms β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Stat β”‚ 1% β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ Avg β”‚ Stdev β”‚ Min β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Req/Sec β”‚ 21087 β”‚ 21087 β”‚ 34623 β”‚ 35487 β”‚ 33258.4 β”‚ 4107.01 β”‚ 21077 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Bytes/Sec β”‚ 3.29 MB β”‚ 3.29 MB β”‚ 5.4 MB β”‚ 5.54 MB β”‚ 5.19 MB β”‚ 641 kB β”‚ 3.29 MB β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Req/Bytes counts sampled once per second.
333k requests in 10.1s, 51.9 MB read
@loige
13
🍾
TIP 2.
FIND YOUR BOTTLENECK
@loige
14
Clinic.js
clinicjs.org
@loige
15
clinic doctor --autocannon [ -c 200 '/?data=ciaoπŸ‘‹' ] -- node server.js
@loige
16
clinic flame --autocannon [ -c 200 '/?data=ciaoπŸ‘‹' ] -- node server.js
@loige
17
clinic bubble --autocannon [ -c 200 '/?data=ciaoπŸ‘‹' ] -- node server.js
@loige
18
🎳
TIP 3.
UNDERSTAND YOUR GOALS
@loige
19
WHAT DO WE OPTIMIZE FOR?
THROUGHPUT?
MEMORY?
LATENCY?
@loige
20
πŸ‘
TIP 4.
ALWAYS "OBSERVE"
@loige
21
I MEAN, IN PRODUCTION!
Logs - Metrics - Traces
@loige
22
πŸš€
TIP 5.
SCALE YOUR ARCHITECTURE
@loige
23
PERFORMANCE != SCALABILITY
@loige
24
HOW CAN WE SCALE A SYSTEM
BY ADDING RESOURCES?
@loige
25
THE " "
SCALE CUBE
x-axis
cloning
z-axis
partitioning
y-axis
functional
decomposition
@loige
26
THE " "
SCALE CUBE
x-axis
cloning
z-axis
partitioning
y-axis
functional
decomposition
@loige
26
27
Reverse proxy
CLONING
Inside the same server
Load Balancer
Using multiple server
@loige
THE MODULE
CLUSTER
Master process
Worker
process
Worker
process
Worker
process
28
@loige
THE MODULE
CLUSTER
Master process
Worker
process
Worker
process
Worker
process
28
@loige
THE MODULE
CLUSTER
Master process
Worker
process
Worker
process
Worker
process
28
@loige
THE MODULE
CLUSTER
Master process
Worker
process
Worker
process
Worker
process
28
@loige
THE MODULE
CLUSTER
Master process
Worker
process
Worker
process
Worker
process
28
@loige
THE MODULE
CLUSTER
Master process
Worker
process
Worker
process
Worker
process
28
@loige
THE MODULE
CLUSTER
Master process
Worker
process
Worker
process
Worker
process
28
@loige
import cluster from 'cluster'
import { cpus } from 'os'
const numCPUs = cpus().length
if (cluster.isMaster) {
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
} else {
// Worker code here...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
@loige
29
import cluster from 'cluster'
import { cpus } from 'os'
const numCPUs = cpus().length
if (cluster.isMaster) {
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
} else {
// Worker code here...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
3-4x req/sec
(8 core)
@loige
29
import cluster from 'cluster'
import { cpus } from 'os'
const numCPUs = cpus().length
if (cluster.isMaster) {
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
} else {
// Worker code here...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
import { cpus } from 'os'
const numCPUs = cpus().length
import cluster from 'cluster'
1
2
3
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
3-4x req/sec
(8 core)
@loige
29
import cluster from 'cluster'
import { cpus } from 'os'
const numCPUs = cpus().length
if (cluster.isMaster) {
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
} else {
// Worker code here...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
import { cpus } from 'os'
const numCPUs = cpus().length
import cluster from 'cluster'
1
2
3
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
if (cluster.isMaster) {
} else {
}
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
11
// Worker code here...
12
13
3-4x req/sec
(8 core)
@loige
29
import cluster from 'cluster'
import { cpus } from 'os'
const numCPUs = cpus().length
if (cluster.isMaster) {
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
} else {
// Worker code here...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
import { cpus } from 'os'
const numCPUs = cpus().length
import cluster from 'cluster'
1
2
3
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
if (cluster.isMaster) {
} else {
}
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
11
// Worker code here...
12
13
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
7
8
9
10
} else {
11
// Worker code here...
12
}
13
3-4x req/sec
(8 core)
@loige
29
import cluster from 'cluster'
import { cpus } from 'os'
const numCPUs = cpus().length
if (cluster.isMaster) {
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
} else {
// Worker code here...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
import { cpus } from 'os'
const numCPUs = cpus().length
import cluster from 'cluster'
1
2
3
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
if (cluster.isMaster) {
} else {
}
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
11
// Worker code here...
12
13
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
7
8
9
10
} else {
11
// Worker code here...
12
}
13
// Worker code here...
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
12
}
13
3-4x req/sec
(8 core)
@loige
29
import cluster from 'cluster'
import { cpus } from 'os'
const numCPUs = cpus().length
if (cluster.isMaster) {
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
} else {
// Worker code here...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
import { cpus } from 'os'
const numCPUs = cpus().length
import cluster from 'cluster'
1
2
3
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
// Worker code here...
12
}
13
if (cluster.isMaster) {
} else {
}
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
11
// Worker code here...
12
13
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
7
8
9
10
} else {
11
// Worker code here...
12
}
13
// Worker code here...
import cluster from 'cluster'
1
import { cpus } from 'os'
2
3
const numCPUs = cpus().length
4
5
if (cluster.isMaster) {
6
// Fork workers
7
for (let i = 0; i < numCPUs; i++) {
8
cluster.fork()
9
}
10
} else {
11
12
}
13
import cluster from 'cluster'
import { cpus } from 'os'
const numCPUs = cpus().length
if (cluster.isMaster) {
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
} else {
// Worker code here...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
3-4x req/sec
(8 core)
@loige
29
YOU COULD ALSO USE
CHECK OUT !
WORKER
THREADS
PISCINA
@loige
30
CLONING IS THE EASIEST STRATEGY TO SCALE A SERVICE...
Β 
... AS LONG AS YOUR APPLICATION IS "STATELESS"
@loige
31
API Gateway
FUNCTIONAL DECOMPOSITION
a.k.a. "Micro-services"
32
/products
/cart
cart DB
products DB
@loige
API Gateway
FUNCTIONAL DECOMPOSITION
a.k.a. "Micro-services"
33
/products
/cart
Functional decomposition can
also be combined with cloning!
cart DB
products DB
@loige
NODE.JS IS GREAT FOR MICROSERVICES
@loige
34
MICROSERVICES CAN ALSO HELP WITH
SCALING THE ORGANISATION!
@loige
35
MICROSERVICES ADD COMPLEXITY
Observability
Deployments
Versioning
Integration
@loige
36
PARTITIONING
Service and Data Partitioning along Customer Boundaries
Shard partitioning
/products/[A-L]/
/products/[M-Z]/
DB 2
37
DB 1
@loige
PARTITIONING IS GENERALLY USED
TO SCALE DATABASES
AND
SAAS SOFTWARE GEOGRAPHICALLY
@loige
38
SUMMARY
@loige
39
SUMMARY
πŸ›«Establish a baseline
@loige
39
SUMMARY
πŸ›«Establish a baseline
🍾Find your bottleneck
@loige
39
SUMMARY
πŸ›«Establish a baseline
🍾Find your bottleneck
🎳Understand your goals
@loige
39
SUMMARY
πŸ›«Establish a baseline
🍾Find your bottleneck
🎳Understand your goals
πŸ‘Always "observe"
@loige
39
SUMMARY
πŸ›«Establish a baseline
🍾Find your bottleneck
🎳Understand your goals
πŸ‘Always "observe"
πŸš€Scale your architecture
(cloning, decomposition & partitioning)
@loige
39
☝nodejsdp.link
THANK YOU!
Special thanks to , ,
, , ,
, , ,
, , , ,
, , , ,
, , , ,
,
Icons and SVGs by
Photo by on
@StefanoAbalsamo @matteocollina
@dagonzago @NullishCoalesce @DublinSvelte
@KViglucci @gjohnson391 @lucamaraschi
@laurekamalandua @giltayar @mrm8488 @adrirai
@harafise @EugeneWare @Jauny @tlivings
@michaelcfine @leojino @shahidontech @Lordoomer
@zsadigov @dottorblaster
freepik.com
Jonas Kaiser Unsplash
@loige
loige.link/node-adc
40

Weitere Γ€hnliche Inhalte

Was ist angesagt?

Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4DEVCON
Β 
REST with Eve and Python
REST with Eve and PythonREST with Eve and Python
REST with Eve and PythonPiXeL16
Β 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4DEVCON
Β 
Implementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile AppsImplementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile AppsMichele Orselli
Β 
Python Code Camp for Professionals 2/4
Python Code Camp for Professionals 2/4Python Code Camp for Professionals 2/4
Python Code Camp for Professionals 2/4DEVCON
Β 
Apache spark with akka couchbase code by bhawani
Apache spark with akka couchbase code by bhawaniApache spark with akka couchbase code by bhawani
Apache spark with akka couchbase code by bhawaniBhawani N Prasad
Β 
An Overview of Node.js
An Overview of Node.jsAn Overview of Node.js
An Overview of Node.jsAyush Mishra
Β 
Data models in Angular 1 & 2
Data models in Angular 1 & 2Data models in Angular 1 & 2
Data models in Angular 1 & 2Adam Klein
Β 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silexMichele Orselli
Β 
Implementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconfImplementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconfMichele Orselli
Β 
Dart Power Tools
Dart Power ToolsDart Power Tools
Dart Power ToolsMatt Norris
Β 
Introduction to Angular js
Introduction to Angular jsIntroduction to Angular js
Introduction to Angular jsMustafa Gamal
Β 
Elasticsearch intro output
Elasticsearch intro outputElasticsearch intro output
Elasticsearch intro outputTom Chen
Β 
Angular Tutorial Freshers and Experienced
Angular Tutorial Freshers and ExperiencedAngular Tutorial Freshers and Experienced
Angular Tutorial Freshers and Experiencedrajkamaltibacademy
Β 
The Ring programming language version 1.5.2 book - Part 44 of 181
The Ring programming language version 1.5.2 book - Part 44 of 181The Ring programming language version 1.5.2 book - Part 44 of 181
The Ring programming language version 1.5.2 book - Part 44 of 181Mahmoud Samir Fayed
Β 
The Big Picture and How to Get Started
The Big Picture and How to Get StartedThe Big Picture and How to Get Started
The Big Picture and How to Get Startedguest1af57e
Β 
Progressive What Apps?
Progressive What Apps?Progressive What Apps?
Progressive What Apps?Patrick Kettner
Β 
Pascarello_Investigating JavaScript and Ajax Security
Pascarello_Investigating JavaScript and Ajax SecurityPascarello_Investigating JavaScript and Ajax Security
Pascarello_Investigating JavaScript and Ajax Securityamiable_indian
Β 
Working Effectively with Legacy Javascript code in Opal
Working Effectively with Legacy Javascript code in OpalWorking Effectively with Legacy Javascript code in Opal
Working Effectively with Legacy Javascript code in OpalForrest Chang
Β 

Was ist angesagt? (20)

Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4
Β 
REST with Eve and Python
REST with Eve and PythonREST with Eve and Python
REST with Eve and Python
Β 
Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4Python Code Camp for Professionals 1/4
Python Code Camp for Professionals 1/4
Β 
Implementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile AppsImplementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile Apps
Β 
Python Code Camp for Professionals 2/4
Python Code Camp for Professionals 2/4Python Code Camp for Professionals 2/4
Python Code Camp for Professionals 2/4
Β 
Apache spark with akka couchbase code by bhawani
Apache spark with akka couchbase code by bhawaniApache spark with akka couchbase code by bhawani
Apache spark with akka couchbase code by bhawani
Β 
An Overview of Node.js
An Overview of Node.jsAn Overview of Node.js
An Overview of Node.js
Β 
Data models in Angular 1 & 2
Data models in Angular 1 & 2Data models in Angular 1 & 2
Data models in Angular 1 & 2
Β 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silex
Β 
Implementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconfImplementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconf
Β 
Dart Power Tools
Dart Power ToolsDart Power Tools
Dart Power Tools
Β 
Introduction to Angular js
Introduction to Angular jsIntroduction to Angular js
Introduction to Angular js
Β 
Elasticsearch intro output
Elasticsearch intro outputElasticsearch intro output
Elasticsearch intro output
Β 
Node.js and Parse
Node.js and ParseNode.js and Parse
Node.js and Parse
Β 
Angular Tutorial Freshers and Experienced
Angular Tutorial Freshers and ExperiencedAngular Tutorial Freshers and Experienced
Angular Tutorial Freshers and Experienced
Β 
The Ring programming language version 1.5.2 book - Part 44 of 181
The Ring programming language version 1.5.2 book - Part 44 of 181The Ring programming language version 1.5.2 book - Part 44 of 181
The Ring programming language version 1.5.2 book - Part 44 of 181
Β 
The Big Picture and How to Get Started
The Big Picture and How to Get StartedThe Big Picture and How to Get Started
The Big Picture and How to Get Started
Β 
Progressive What Apps?
Progressive What Apps?Progressive What Apps?
Progressive What Apps?
Β 
Pascarello_Investigating JavaScript and Ajax Security
Pascarello_Investigating JavaScript and Ajax SecurityPascarello_Investigating JavaScript and Ajax Security
Pascarello_Investigating JavaScript and Ajax Security
Β 
Working Effectively with Legacy Javascript code in Opal
Working Effectively with Legacy Javascript code in OpalWorking Effectively with Legacy Javascript code in Opal
Working Effectively with Legacy Javascript code in Opal
Β 

Γ„hnlich wie Node.js: scalability tips - Azure Dev Community Vijayawada

Node.js server-side rendering
Node.js server-side renderingNode.js server-side rendering
Node.js server-side renderingThe Software House
Β 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013Laurent_VB
Β 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)Igor Bronovskyy
Β 
Micro app-framework - NodeLive Boston
Micro app-framework - NodeLive BostonMicro app-framework - NodeLive Boston
Micro app-framework - NodeLive BostonMichael Dawson
Β 
Micro app-framework
Micro app-frameworkMicro app-framework
Micro app-frameworkMichael Dawson
Β 
Angular server side rendering - Strategies & Technics
Angular server side rendering - Strategies & Technics Angular server side rendering - Strategies & Technics
Angular server side rendering - Strategies & Technics Eliran Eliassy
Β 
Engage 2023: Taking Domino Apps to the next level by providing a Rest API
Engage 2023: Taking Domino Apps to the next level by providing a Rest APIEngage 2023: Taking Domino Apps to the next level by providing a Rest API
Engage 2023: Taking Domino Apps to the next level by providing a Rest APISerdar Basegmez
Β 
bbyopenApp_Code.DS_StorebbyopenApp_CodeVBCodeGoogleMaps.docx
bbyopenApp_Code.DS_StorebbyopenApp_CodeVBCodeGoogleMaps.docxbbyopenApp_Code.DS_StorebbyopenApp_CodeVBCodeGoogleMaps.docx
bbyopenApp_Code.DS_StorebbyopenApp_CodeVBCodeGoogleMaps.docxikirkton
Β 
Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Remy Sharp
Β 
Is html5-ready-workshop-110727181512-phpapp02
Is html5-ready-workshop-110727181512-phpapp02Is html5-ready-workshop-110727181512-phpapp02
Is html5-ready-workshop-110727181512-phpapp02PL dream
Β 
HTML5: huh, what is it good for?
HTML5: huh, what is it good for?HTML5: huh, what is it good for?
HTML5: huh, what is it good for?Remy Sharp
Β 
Enhance Web Performance
Enhance Web PerformanceEnhance Web Performance
Enhance Web PerformanceAdam Lu
Β 
A mobile web app for Android in 75 minutes
A mobile web app for Android in 75 minutesA mobile web app for Android in 75 minutes
A mobile web app for Android in 75 minutesJames Pearce
Β 
Maciej Treder "Server-side rendering with Angularβ€”be faster and more SEO, CDN...
Maciej Treder "Server-side rendering with Angularβ€”be faster and more SEO, CDN...Maciej Treder "Server-side rendering with Angularβ€”be faster and more SEO, CDN...
Maciej Treder "Server-side rendering with Angularβ€”be faster and more SEO, CDN...Fwdays
Β 
The Future of CSS with Web components
The Future of CSS with Web componentsThe Future of CSS with Web components
The Future of CSS with Web componentsdevObjective
Β 
The Future of CSS with Web Components
The Future of CSS with Web ComponentsThe Future of CSS with Web Components
The Future of CSS with Web ComponentsColdFusionConference
Β 
DataStax: 0 to App faster with Ruby and NodeJS
DataStax: 0 to App faster with Ruby and NodeJSDataStax: 0 to App faster with Ruby and NodeJS
DataStax: 0 to App faster with Ruby and NodeJSDataStax Academy
Β 

Γ„hnlich wie Node.js: scalability tips - Azure Dev Community Vijayawada (20)

Node.js server-side rendering
Node.js server-side renderingNode.js server-side rendering
Node.js server-side rendering
Β 
Nodejs.meetup
Nodejs.meetupNodejs.meetup
Nodejs.meetup
Β 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013
Β 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
Β 
Micro app-framework - NodeLive Boston
Micro app-framework - NodeLive BostonMicro app-framework - NodeLive Boston
Micro app-framework - NodeLive Boston
Β 
Micro app-framework
Micro app-frameworkMicro app-framework
Micro app-framework
Β 
Angular server side rendering - Strategies & Technics
Angular server side rendering - Strategies & Technics Angular server side rendering - Strategies & Technics
Angular server side rendering - Strategies & Technics
Β 
Engage 2023: Taking Domino Apps to the next level by providing a Rest API
Engage 2023: Taking Domino Apps to the next level by providing a Rest APIEngage 2023: Taking Domino Apps to the next level by providing a Rest API
Engage 2023: Taking Domino Apps to the next level by providing a Rest API
Β 
bbyopenApp_Code.DS_StorebbyopenApp_CodeVBCodeGoogleMaps.docx
bbyopenApp_Code.DS_StorebbyopenApp_CodeVBCodeGoogleMaps.docxbbyopenApp_Code.DS_StorebbyopenApp_CodeVBCodeGoogleMaps.docx
bbyopenApp_Code.DS_StorebbyopenApp_CodeVBCodeGoogleMaps.docx
Β 
Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)
Β 
Is html5-ready-workshop-110727181512-phpapp02
Is html5-ready-workshop-110727181512-phpapp02Is html5-ready-workshop-110727181512-phpapp02
Is html5-ready-workshop-110727181512-phpapp02
Β 
HTML5: huh, what is it good for?
HTML5: huh, what is it good for?HTML5: huh, what is it good for?
HTML5: huh, what is it good for?
Β 
Enhance Web Performance
Enhance Web PerformanceEnhance Web Performance
Enhance Web Performance
Β 
A mobile web app for Android in 75 minutes
A mobile web app for Android in 75 minutesA mobile web app for Android in 75 minutes
A mobile web app for Android in 75 minutes
Β 
Maciej Treder "Server-side rendering with Angularβ€”be faster and more SEO, CDN...
Maciej Treder "Server-side rendering with Angularβ€”be faster and more SEO, CDN...Maciej Treder "Server-side rendering with Angularβ€”be faster and more SEO, CDN...
Maciej Treder "Server-side rendering with Angularβ€”be faster and more SEO, CDN...
Β 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.js
Β 
The Future of CSS with Web components
The Future of CSS with Web componentsThe Future of CSS with Web components
The Future of CSS with Web components
Β 
The Future of CSS with Web Components
The Future of CSS with Web ComponentsThe Future of CSS with Web Components
The Future of CSS with Web Components
Β 
DataStax: 0 to App faster with Ruby and NodeJS
DataStax: 0 to App faster with Ruby and NodeJSDataStax: 0 to App faster with Ruby and NodeJS
DataStax: 0 to App faster with Ruby and NodeJS
Β 
Having Fun with Play
Having Fun with PlayHaving Fun with Play
Having Fun with Play
Β 

Mehr von Luciano Mammino

Did you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSDid you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSLuciano Mammino
Β 
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...Luciano Mammino
Β 
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoBuilding an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoLuciano Mammino
Β 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperLuciano Mammino
Β 
Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Luciano Mammino
Β 
Everything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsEverything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsLuciano Mammino
Β 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance ComputingLuciano Mammino
Β 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance ComputingLuciano Mammino
Β 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022Luciano Mammino
Β 
Building an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableBuilding an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableLuciano Mammino
Β 
Let's take the monolith to the cloud πŸš€
Let's take the monolith to the cloud πŸš€Let's take the monolith to the cloud πŸš€
Let's take the monolith to the cloud πŸš€Luciano Mammino
Β 
A look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinA look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinLuciano Mammino
Β 
Monoliths to the cloud!
Monoliths to the cloud!Monoliths to the cloud!
Monoliths to the cloud!Luciano Mammino
Β 
A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)Luciano Mammino
Β 
AWS Observability Made Simple
AWS Observability Made SimpleAWS Observability Made Simple
AWS Observability Made SimpleLuciano Mammino
Β 
Semplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessSemplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessLuciano Mammino
Β 
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Luciano Mammino
Β 
Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Luciano Mammino
Β 
How to send gzipped requests with boto3
How to send gzipped requests with boto3How to send gzipped requests with boto3
How to send gzipped requests with boto3Luciano Mammino
Β 

Mehr von Luciano Mammino (20)

Did you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSDid you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJS
Β 
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
Β 
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoBuilding an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Β 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiper
Β 
Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!
Β 
Everything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsEverything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLs
Β 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
Β 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
Β 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
Β 
Building an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableBuilding an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & Airtable
Β 
Let's take the monolith to the cloud πŸš€
Let's take the monolith to the cloud πŸš€Let's take the monolith to the cloud πŸš€
Let's take the monolith to the cloud πŸš€
Β 
A look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinA look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust Dublin
Β 
Monoliths to the cloud!
Monoliths to the cloud!Monoliths to the cloud!
Monoliths to the cloud!
Β 
The senior dev
The senior devThe senior dev
The senior dev
Β 
A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)
Β 
AWS Observability Made Simple
AWS Observability Made SimpleAWS Observability Made Simple
AWS Observability Made Simple
Β 
Semplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessSemplificare l'observability per progetti Serverless
Semplificare l'observability per progetti Serverless
Β 
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Β 
Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021
Β 
How to send gzipped requests with boto3
How to send gzipped requests with boto3How to send gzipped requests with boto3
How to send gzipped requests with boto3
Β 

KΓΌrzlich hochgeladen

Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
Β 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
Β 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
Β 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
Β 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
Β 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Zilliz
Β 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
Β 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
Β 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
Β 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
Β 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
Β 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
Β 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
Β 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
Β 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
Β 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
Β 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
Β 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vΓ‘zquez
Β 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Angeliki Cooney
Β 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
Β 

KΓΌrzlich hochgeladen (20)

Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Β 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Β 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
Β 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
Β 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
Β 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Β 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Β 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
Β 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
Β 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
Β 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
Β 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
Β 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
Β 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
Β 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
Β 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
Β 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
Β 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Β 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Β 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
Β 

Node.js: scalability tips - Azure Dev Community Vijayawada

  • 1. NODE.JS SCALABILITY TIPS NODE.JS SCALABILITY TIPS Luciano Mammino ( ) @loige loige.link/node-adc Vijayawada - 2021-12-13 1
  • 2. @loige Get the slides! πŸ‘‡ loige.link/node-adc 2
  • 5. HELLO! πŸ‘‹I'm LucianoΒ ( πŸ•πŸ ) Senior Architect @ fourTheorem (Dublin ) 3
  • 6. HELLO! πŸ‘‹I'm LucianoΒ ( πŸ•πŸ ) Senior Architect @ fourTheorem (Dublin ) nodejsdp.link πŸ“”Co-Author of Node.js Design PatternsΒ  πŸ‘‰ 3
  • 7. HELLO! πŸ‘‹I'm LucianoΒ ( πŸ•πŸ ) Senior Architect @ fourTheorem (Dublin ) nodejsdp.link πŸ“”Co-Author of Node.js Design PatternsΒ  πŸ‘‰ Let's connect! Β  (blog) Β  (twitter) Β  (twitch) Β  (github) loige.co @loige loige lmammino 3
  • 8. WE ARE BUSINESS FOCUSED TECHNOLOGISTS THAT DELIVER. Β | Β | Accelerated Serverless AI as a Service Platform Modernisation We are hiring: do you want to ? work with us loige 4
  • 9. "A service is said to be scalable if when we increase the resources in a system, it results in increased performance in a manner proportional to resources added" β€” Werner Vogels @loige 5
  • 10. πŸ›« TIP 1. ESTABLISH A BASELINE @loige 6
  • 12. import { createServer } from 'http' import QRCode from 'qrcode' createServer(function handler (req, res) { const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } res.writeHead(200, { 'Content-Type': 'image/png' }) QRCode.toFileStream(res, data, { width: 300 }) }).listen(8080) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @loige 8
  • 13. import { createServer } from 'http' import QRCode from 'qrcode' createServer(function handler (req, res) { const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } res.writeHead(200, { 'Content-Type': 'image/png' }) QRCode.toFileStream(res, data, { width: 300 }) }).listen(8080) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { createServer } from 'http' import QRCode from 'qrcode' 1 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 @loige 8
  • 14. import { createServer } from 'http' import QRCode from 'qrcode' createServer(function handler (req, res) { const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } res.writeHead(200, { 'Content-Type': 'image/png' }) QRCode.toFileStream(res, data, { width: 300 }) }).listen(8080) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { createServer } from 'http' import QRCode from 'qrcode' 1 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 createServer(function handler (req, res) { }).listen(8080) import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 18 @loige 8
  • 15. import { createServer } from 'http' import QRCode from 'qrcode' createServer(function handler (req, res) { const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } res.writeHead(200, { 'Content-Type': 'image/png' }) QRCode.toFileStream(res, data, { width: 300 }) }).listen(8080) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { createServer } from 'http' import QRCode from 'qrcode' 1 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 createServer(function handler (req, res) { }).listen(8080) import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 18 const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 createServer(function handler (req, res) { 4 5 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 @loige 8
  • 16. import { createServer } from 'http' import QRCode from 'qrcode' createServer(function handler (req, res) { const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } res.writeHead(200, { 'Content-Type': 'image/png' }) QRCode.toFileStream(res, data, { width: 300 }) }).listen(8080) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { createServer } from 'http' import QRCode from 'qrcode' 1 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 createServer(function handler (req, res) { }).listen(8080) import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 18 const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 createServer(function handler (req, res) { 4 5 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 7 8 9 10 11 12 13 14 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 @loige 8
  • 17. import { createServer } from 'http' import QRCode from 'qrcode' createServer(function handler (req, res) { const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } res.writeHead(200, { 'Content-Type': 'image/png' }) QRCode.toFileStream(res, data, { width: 300 }) }).listen(8080) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { createServer } from 'http' import QRCode from 'qrcode' 1 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 createServer(function handler (req, res) { }).listen(8080) import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 18 const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 createServer(function handler (req, res) { 4 5 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 7 8 9 10 11 12 13 14 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 res.writeHead(200, { 'Content-Type': 'image/png' }) QRCode.toFileStream(res, data, { width: 300 }) import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 16 17 }).listen(8080) 18 @loige 8
  • 18. import { createServer } from 'http' import QRCode from 'qrcode' createServer(function handler (req, res) { const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } res.writeHead(200, { 'Content-Type': 'image/png' }) QRCode.toFileStream(res, data, { width: 300 }) }).listen(8080) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import { createServer } from 'http' import QRCode from 'qrcode' 1 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 createServer(function handler (req, res) { }).listen(8080) import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 18 const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 createServer(function handler (req, res) { 4 5 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 7 8 9 10 11 12 13 14 15 res.writeHead(200, { 'Content-Type': 'image/png' }) 16 QRCode.toFileStream(res, data, { width: 300 }) 17 }).listen(8080) 18 res.writeHead(200, { 'Content-Type': 'image/png' }) QRCode.toFileStream(res, data, { width: 300 }) import { createServer } from 'http' 1 import QRCode from 'qrcode' 2 3 createServer(function handler (req, res) { 4 const url = new URL(req.url, 'http://localhost:8080') 5 const data = url.searchParams.get('data') 6 if (!data) { 7 res.writeHead(200, {'Content-Type': 'text/html'}) 8 return res.end(`<html> 9 <body> 10 <p>To use this app you need to set the <code>data</code> querystrin 11 <p>Try for example <a href="/?data=hello">/?data=hello</a></p> 12 </body> 13 </html>`) 14 } 15 16 17 }).listen(8080) 18 import { createServer } from 'http' import QRCode from 'qrcode' createServer(function handler (req, res) { const url = new URL(req.url, 'http://localhost:8080') const data = url.searchParams.get('data') if (!data) { res.writeHead(200, {'Content-Type': 'text/html'}) return res.end(`<html> <body> <p>To use this app you need to set the <code>data</code> querystrin <p>Try for example <a href="/?data=hello">/?data=hello</a></p> </body> </html>`) } res.writeHead(200, { 'Content-Type': 'image/png' }) QRCode.toFileStream(res, data, { width: 300 }) }).listen(8080) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @loige 8
  • 19. autocannon -c 200 --on-port / -- node server.js WRK node server.js& wrk -t8 -c200 -d10s http://localhost:8080/ @loige 9
  • 20. autocannon -c 200 --on-port /?data=ciaoπŸ‘‹ -- node server.js Running 10s test @ http://localhost:8080/?data=ciaoπŸ‘‹ 200 connections β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Stat β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ 99% β”‚ Avg β”‚ Stdev β”‚ Max β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Latency β”‚ 1899 ms β”‚ 1951 ms β”‚ 2053 ms β”‚ 2054 ms β”‚ 1964.92 ms β”‚ 99.9 ms β”‚ 3364.03 ms β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Stat β”‚ 1% β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ Avg β”‚ Stdev β”‚ Min β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Req/Sec β”‚ 0 β”‚ 0 β”‚ 30 β”‚ 199 β”‚ 99.5 β”‚ 94.27 β”‚ 30 β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Bytes/Sec β”‚ 0 B β”‚ 0 B β”‚ 50.7 kB β”‚ 336 kB β”‚ 168 kB β”‚ 159 kB β”‚ 50.7 kB β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ Req/Bytes counts sampled once per second. 995 requests in 10.08s, 1.68 MB read @loige 10
  • 21. autocannon -c 200 --on-port /?data=ciaoπŸ‘‹ -- node server.js Running 10s test @ http://localhost:8080/?data=ciaoπŸ‘‹ 200 connections β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Stat β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ 99% β”‚ Avg β”‚ Stdev β”‚ Max β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Latency β”‚ 1899 ms β”‚ 1951 ms β”‚ 2053 ms β”‚ 2054 ms β”‚ 1964.92 ms β”‚ 99.9 ms β”‚ 3364.03 ms β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Stat β”‚ 1% β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ Avg β”‚ Stdev β”‚ Min β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Req/Sec β”‚ 0 β”‚ 0 β”‚ 30 β”‚ 199 β”‚ 99.5 β”‚ 94.27 β”‚ 30 β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Bytes/Sec β”‚ 0 B β”‚ 0 B β”‚ 50.7 kB β”‚ 336 kB β”‚ 168 kB β”‚ 159 kB β”‚ 50.7 kB β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ Req/Bytes counts sampled once per second. 995 requests in 10.08s, 1.68 MB read @loige 10
  • 22. β›… TIP 1-BIS ALSO, FIND OUT YOUR CEILING @loige 11
  • 23. import { createServer } from 'http' createServer((req, res) => { if (req.method === 'GET' && req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/plain' }) res.end('Hello Worldn') } else { res.statusCode = 404 res.end() } }).listen(8080) 1 2 3 4 5 6 7 8 9 10 11 @loige 12
  • 24. import { createServer } from 'http' createServer((req, res) => { if (req.method === 'GET' && req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/plain' }) res.end('Hello Worldn') } else { res.statusCode = 404 res.end() } }).listen(8080) 1 2 3 4 5 6 7 8 9 10 11 res.writeHead(200, { 'Content-Type': 'text/plain' }) res.end('Hello Worldn') import { createServer } from 'http' 1 2 createServer((req, res) => { 3 if (req.method === 'GET' && req.url === '/') { 4 5 6 } else { 7 res.statusCode = 404 8 res.end() 9 } 10 }).listen(8080) 11 @loige 12
  • 25. autocannon -c 200 --on-port / -- node server.js Running 10s test @ http://localhost:8080/ 200 connections β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Stat β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ 99% β”‚ Avg β”‚ Stdev β”‚ Max β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Latency β”‚ 3 ms β”‚ 5 ms β”‚ 11 ms β”‚ 14 ms β”‚ 5.51 ms β”‚ 2.71 ms β”‚ 80.63 ms β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Stat β”‚ 1% β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ Avg β”‚ Stdev β”‚ Min β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Req/Sec β”‚ 21087 β”‚ 21087 β”‚ 34623 β”‚ 35487 β”‚ 33258.4 β”‚ 4107.01 β”‚ 21077 β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Bytes/Sec β”‚ 3.29 MB β”‚ 3.29 MB β”‚ 5.4 MB β”‚ 5.54 MB β”‚ 5.19 MB β”‚ 641 kB β”‚ 3.29 MB β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ Req/Bytes counts sampled once per second. 333k requests in 10.1s, 51.9 MB read @loige 13
  • 26. autocannon -c 200 --on-port / -- node server.js Running 10s test @ http://localhost:8080/ 200 connections β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Stat β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ 99% β”‚ Avg β”‚ Stdev β”‚ Max β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Latency β”‚ 3 ms β”‚ 5 ms β”‚ 11 ms β”‚ 14 ms β”‚ 5.51 ms β”‚ 2.71 ms β”‚ 80.63 ms β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Stat β”‚ 1% β”‚ 2.5% β”‚ 50% β”‚ 97.5% β”‚ Avg β”‚ Stdev β”‚ Min β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Req/Sec β”‚ 21087 β”‚ 21087 β”‚ 34623 β”‚ 35487 β”‚ 33258.4 β”‚ 4107.01 β”‚ 21077 β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Bytes/Sec β”‚ 3.29 MB β”‚ 3.29 MB β”‚ 5.4 MB β”‚ 5.54 MB β”‚ 5.19 MB β”‚ 641 kB β”‚ 3.29 MB β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ Req/Bytes counts sampled once per second. 333k requests in 10.1s, 51.9 MB read @loige 13
  • 27. 🍾 TIP 2. FIND YOUR BOTTLENECK @loige 14
  • 29. clinic doctor --autocannon [ -c 200 '/?data=ciaoπŸ‘‹' ] -- node server.js @loige 16
  • 30. clinic flame --autocannon [ -c 200 '/?data=ciaoπŸ‘‹' ] -- node server.js @loige 17
  • 31. clinic bubble --autocannon [ -c 200 '/?data=ciaoπŸ‘‹' ] -- node server.js @loige 18
  • 33. WHAT DO WE OPTIMIZE FOR? THROUGHPUT? MEMORY? LATENCY? @loige 20
  • 35. I MEAN, IN PRODUCTION! Logs - Metrics - Traces @loige 22
  • 36. πŸš€ TIP 5. SCALE YOUR ARCHITECTURE @loige 23
  • 38. HOW CAN WE SCALE A SYSTEM BY ADDING RESOURCES? @loige 25
  • 39. THE " " SCALE CUBE x-axis cloning z-axis partitioning y-axis functional decomposition @loige 26
  • 40. THE " " SCALE CUBE x-axis cloning z-axis partitioning y-axis functional decomposition @loige 26
  • 41. 27 Reverse proxy CLONING Inside the same server Load Balancer Using multiple server @loige
  • 49. import cluster from 'cluster' import { cpus } from 'os' const numCPUs = cpus().length if (cluster.isMaster) { // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } } else { // Worker code here... } 1 2 3 4 5 6 7 8 9 10 11 12 13 @loige 29
  • 50. import cluster from 'cluster' import { cpus } from 'os' const numCPUs = cpus().length if (cluster.isMaster) { // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } } else { // Worker code here... } 1 2 3 4 5 6 7 8 9 10 11 12 13 import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 3-4x req/sec (8 core) @loige 29
  • 51. import cluster from 'cluster' import { cpus } from 'os' const numCPUs = cpus().length if (cluster.isMaster) { // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } } else { // Worker code here... } 1 2 3 4 5 6 7 8 9 10 11 12 13 import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 import { cpus } from 'os' const numCPUs = cpus().length import cluster from 'cluster' 1 2 3 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 3-4x req/sec (8 core) @loige 29
  • 52. import cluster from 'cluster' import { cpus } from 'os' const numCPUs = cpus().length if (cluster.isMaster) { // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } } else { // Worker code here... } 1 2 3 4 5 6 7 8 9 10 11 12 13 import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 import { cpus } from 'os' const numCPUs = cpus().length import cluster from 'cluster' 1 2 3 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 if (cluster.isMaster) { } else { } import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 11 // Worker code here... 12 13 3-4x req/sec (8 core) @loige 29
  • 53. import cluster from 'cluster' import { cpus } from 'os' const numCPUs = cpus().length if (cluster.isMaster) { // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } } else { // Worker code here... } 1 2 3 4 5 6 7 8 9 10 11 12 13 import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 import { cpus } from 'os' const numCPUs = cpus().length import cluster from 'cluster' 1 2 3 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 if (cluster.isMaster) { } else { } import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 11 // Worker code here... 12 13 // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 7 8 9 10 } else { 11 // Worker code here... 12 } 13 3-4x req/sec (8 core) @loige 29
  • 54. import cluster from 'cluster' import { cpus } from 'os' const numCPUs = cpus().length if (cluster.isMaster) { // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } } else { // Worker code here... } 1 2 3 4 5 6 7 8 9 10 11 12 13 import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 import { cpus } from 'os' const numCPUs = cpus().length import cluster from 'cluster' 1 2 3 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 if (cluster.isMaster) { } else { } import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 11 // Worker code here... 12 13 // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 7 8 9 10 } else { 11 // Worker code here... 12 } 13 // Worker code here... import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 12 } 13 3-4x req/sec (8 core) @loige 29
  • 55. import cluster from 'cluster' import { cpus } from 'os' const numCPUs = cpus().length if (cluster.isMaster) { // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } } else { // Worker code here... } 1 2 3 4 5 6 7 8 9 10 11 12 13 import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 import { cpus } from 'os' const numCPUs = cpus().length import cluster from 'cluster' 1 2 3 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 // Worker code here... 12 } 13 if (cluster.isMaster) { } else { } import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 11 // Worker code here... 12 13 // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 7 8 9 10 } else { 11 // Worker code here... 12 } 13 // Worker code here... import cluster from 'cluster' 1 import { cpus } from 'os' 2 3 const numCPUs = cpus().length 4 5 if (cluster.isMaster) { 6 // Fork workers 7 for (let i = 0; i < numCPUs; i++) { 8 cluster.fork() 9 } 10 } else { 11 12 } 13 import cluster from 'cluster' import { cpus } from 'os' const numCPUs = cpus().length if (cluster.isMaster) { // Fork workers for (let i = 0; i < numCPUs; i++) { cluster.fork() } } else { // Worker code here... } 1 2 3 4 5 6 7 8 9 10 11 12 13 3-4x req/sec (8 core) @loige 29
  • 56. YOU COULD ALSO USE CHECK OUT ! WORKER THREADS PISCINA @loige 30
  • 57. CLONING IS THE EASIEST STRATEGY TO SCALE A SERVICE... Β  ... AS LONG AS YOUR APPLICATION IS "STATELESS" @loige 31
  • 58. API Gateway FUNCTIONAL DECOMPOSITION a.k.a. "Micro-services" 32 /products /cart cart DB products DB @loige
  • 59. API Gateway FUNCTIONAL DECOMPOSITION a.k.a. "Micro-services" 33 /products /cart Functional decomposition can also be combined with cloning! cart DB products DB @loige
  • 60. NODE.JS IS GREAT FOR MICROSERVICES @loige 34
  • 61. MICROSERVICES CAN ALSO HELP WITH SCALING THE ORGANISATION! @loige 35
  • 63. PARTITIONING Service and Data Partitioning along Customer Boundaries Shard partitioning /products/[A-L]/ /products/[M-Z]/ DB 2 37 DB 1 @loige
  • 64. PARTITIONING IS GENERALLY USED TO SCALE DATABASES AND SAAS SOFTWARE GEOGRAPHICALLY @loige 38
  • 68. SUMMARY πŸ›«Establish a baseline 🍾Find your bottleneck 🎳Understand your goals @loige 39
  • 69. SUMMARY πŸ›«Establish a baseline 🍾Find your bottleneck 🎳Understand your goals πŸ‘Always "observe" @loige 39
  • 70. SUMMARY πŸ›«Establish a baseline 🍾Find your bottleneck 🎳Understand your goals πŸ‘Always "observe" πŸš€Scale your architecture (cloning, decomposition & partitioning) @loige 39
  • 71. ☝nodejsdp.link THANK YOU! Special thanks to , , , , , , , , , , , , , , , , , , , , , Icons and SVGs by Photo by on @StefanoAbalsamo @matteocollina @dagonzago @NullishCoalesce @DublinSvelte @KViglucci @gjohnson391 @lucamaraschi @laurekamalandua @giltayar @mrm8488 @adrirai @harafise @EugeneWare @Jauny @tlivings @michaelcfine @leojino @shahidontech @Lordoomer @zsadigov @dottorblaster freepik.com Jonas Kaiser Unsplash @loige loige.link/node-adc 40