MICROSERVICES USING
NODE.JS AND
RABBITMQ
Case
Share your location
with your friends
API
Back-end
Key = DevOps
Microservices
↓
Microdeployments
Reasons
Team
Architecture
Best
Practices
Code
Review
Tests
Continuous
Integration
Continuous
Delivery
Continuous
Monitoring
User Message
Lorem
Ipsum
Dolor
Sit
Amet
Libraries
Results
after
10 months
Startup
5 back-end developers
7 micro-services
Positives
New
technologies
Minimum
effort/impact
MySQL
MySQL
Postgre
SQL
Postgre
SQL
MySQL
Postgre
SQL
Postgre
SQL
Polyglot
Persistence
Decoupled
Code
Each
service has
a scope
Negatives
Shotgun
effect
Granular
Release
Unstable
Interfaces
User Message
Integration
Tests
Slow
Docker
New
developers
User-service
dependency
User Message
Lorem
Ipsum
Dolor
Sit
Amet
Lorem
Ipsum
Dolor
Amet
Microservices
Client Server
Server
1 const express = require('express');
2 const bodyParser = require('body-parser');
3
4 const app = express();
5 app.use(bodyParser.json());
6
7 app.listen(3000, () => {
8 console.log(' [x] Awaiting for requests');
9 });
10
11 app.get('/:id', (request, response) => {
12 const id = request.params.id;
13
14 console.log(` [.] ID ${id}`);
15
16 response.status(200).json({
17 data: {
18 name: 'Ada Lovelace',
19 occupation: 'Programmer'
20 }
21 });
22 });
1 app.listen(3000, () => {
2 console.log(' [x] Awaiting for requests');
3 });
4
5 app.get('/:id', (request, response) => {
6 const id = request.params.id;
7
8 console.log(` [.] ID ${id}`);
9
10 response.status(200).json({
11 data: {
12 name: 'Ada Lovelace',
13 occupation: 'Programmer'
14 }
15 });
16 });
Client
1 const express = require('express');
2 const request = require('request-promise');
3
4 const id = process.argv.slice(2);
5
6 const app = express();
7
8 app.listen(3005, () => {
9 console.log(` [x] Requesting user ${id}`);
10
11 request(`http://localhost:3000/${id}`)
12 .then((res) => {
13 return console.log(` [.] Got ${res}`)
14 });
15 });
1 const id = process.argv.slice(2);
2
3 app.listen(3005, () => {
4 console.log(` [x] Requesting user ${id}`);
5
6 request(`http://localhost:3000/${id}`)
7 .then((res) => {
8 return console.log(` [.] Got ${res}`)
9 });
10 });
Result
Client
Fault
resilience
Message
Broker
AMPQ
Advanced Message Queuing
Protocol
Exchange
asynchronous
messages
Reliability
RPC
Remote Procedure Call
Queueing
Client ServerRPC
Server
1 const amqp = require('amqplib/callback_api');
2
3 amqp.connect('amqp://localhost', (err, conn) => {
4 conn.createChannel((err, ch) => {
5 const q = 'rpc_queue';
6
7 ch.assertQueue(q, { durable: false });
8 ch.prefetch(1);
9
10 console.log(' [x] Awaiting RPC requests');
11
12 ch.consume(q, function reply(msg) {
13 const id = parseInt(msg.content.toString(), 10);
14
15 console.log(` [.] ID ${id}`);
16
17 ch.sendToQueue(msg.properties.replyTo,
18 new Buffer('name: Ada Lovelace, occupation: programmer'),
19 { correlationId: msg.properties.correlationId });
20
21 ch.ack(msg);
22 });
23 });
24 });
rpc_queue
Response
Channel
3 amqp.connect('amqp://localhost', (err, conn) => {
4 conn.createChannel((err, ch) => {
5 const q = 'rpc_queue';
Retrieve message
from rpc_queue
12 ch.consume(q, function reply(msg) {
13 const id = parseInt(msg.content.toString(), 10);
14
15 console.log(` [.] ID ${id}`);
Send response
to callback queue
17 ch.sendToQueue(msg.properties.replyTo,
18 new Buffer('name: Ada Lovelace, occupation:
programmer’),
19 { correlationId: msg.properties.correlationId });
Client
1 const amqp = require('amqplib/callback_api');
2 const uuid = require('uuid');
3
4 const id = process.argv.slice(2);
5
6 amqp.connect('amqp://localhost', (err, conn) => {
7 conn.createChannel((err, ch) => {
8 ch.assertQueue('', { exclusive: true }, (err, q) => {
9
10 const corr = uuid();
11 console.log(` [x] Requesting user ${id}`);
12
13 ch.consume(q.queue, (msg) => {
14 if (msg.properties.correlationId === corr) {
15 console.log(` [.] Got ${msg.content.toString()}`);
16 setTimeout(function() { conn.close(); process.exit(0) }, 500);
17 }
18 }, {noAck: true});
19
20 ch.sendToQueue('rpc_queue',
21 new Buffer(id.toString()),
22 { correlationId: corr, replyTo: q.queue });
23 });
24 });
25 });
Callback Queue
Request
Channel
6 amqp.connect('amqp://localhost', (err, conn) => {
7 conn.createChannel((err, ch) => {
8 ch.assertQueue('', { exclusive: true }, (err, q) => {
Request to rpc_queue
10 const corr = uuid();
20 ch.sendToQueue('rpc_queue',
21 new Buffer(id.toString()),
22 { correlationId: corr, replyTo: q.queue });
Retrieve response
from callback queue
13 ch.consume(q.queue, (msg) => {
14 if (msg.properties.correlationId === corr) {
15 console.log(` [.] Got ${msg.content.toString()}`);
16 setTimeout(function() { conn.close();
process.exit(0) }, 500);
17 }
18 }, {noAck: true});
Result
Scalability
Round-Robin
Queues
Performance
Conclusion
Any organization that designs a system (defined broadly)
will produce a design whose structure is a copy of the
organization's communication structure.
Conway's Law
Engineering
Trade-Off
How to solve
my team
problems?
Shotgun effect
Unstable interfaces
Integration tests
User-service
dependency
Monolith
Partially
User Message
Lorem
Ipsum
Dolor
Sit Amet
User LoremIpsum
Shotgun effect
Unstable interfaces
Integration tests
User-service
dependency
Community
Let technology empower
you!
Thanks!
https://github.com/carolpc
https://twitter.com/CarolinaPascale
carolina.pascale.c@gmail.com

Microservices using Node.js and RabbitMQ