Luciano Mammino (@loige)
Vijayawada - 2021-12-13
Get the slides! ๐
๐ I'm Lucianoย (๐ฎ๐น๐๐๐ค)
๐จโ๐ป Senior Architect @ fourTheorem (Dublin ๐ฎ๐ช)
๐ Co-Author of Node.js Design Patternsย ๐
Accelerated Serverlessย | AI as a Serviceย | Platform Modernisation
We are hiring: do you want to work with us?
"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
/?data=ciao๐
Site: qrgen.lmammino.repl.coย - Code: replit.com/@lmammino/QRGen
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> querystring parameter.</p>
<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)
autocannon -c 200 --on-port / -- node server.js
node server.js&
wrk -t8 -c200 -d10s http://localhost:8080/
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
import { createServer } from 'http'
createServer((req, res) => {
if (req.method === 'GET' && req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Hello World\n')
} else {
res.statusCode = 404
res.end()
}
}).listen(8080)
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
clinic doctor --autocannon [ -c 200 '/?data=ciao๐' ] -- node server.js
clinic flame --autocannon [ -c 200 '/?data=ciao๐' ] -- node server.js
clinic bubble --autocannon [ -c 200 '/?data=ciao๐' ] -- node server.js
Logs - Metrics - Traces
x-axis
cloning
z-axis
partitioning
y-axis
functional decomposition
Inside the same server
Load Balancer
Using multiple server
Reverse proxy
Master process
Worker process
Worker process
Worker process
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...
}
3-4x req/sec
(8 core)
a.k.a. "Micro-services"
API Gateway
/products
/cart
products DB
cart DB
a.k.a. "Micro-services"
API Gateway
/products
/cart
Functional decomposition can also be combined with cloning!
products DB
cart DB
Service and Data Partitioning along Customer Boundaries
Shard partitioning
/products/[A-L]/
/products/[M-Z]/
DB 1
DB 2
๐ซ Establish a baseline
๐พ Find your bottleneck
๐ณ Understand your goals
๐ Always "observe"
๐ Scale your architecture
(cloning, decomposition & partitioning)
Special thanks to @StefanoAbalsamo, @matteocollina, @dagonzago, @NullishCoalesce, @DublinSvelte, @KViglucci, @gjohnson391, @lucamaraschi, @laurekamalandua, @giltayar, @mrm8488, @adrirai, @harafise, @EugeneWare, @Jauny, @tlivings, @michaelcfine, @leojino, @shahidontech, @Lordoomer, @zsadigov, @dottorblaster
Icons and SVGs by freepik.com
Photo by Jonas Kaiser on Unsplash
โ๏ธ nodejsdp.link