SlideShare a Scribd company logo
1 of 81
Download to read offline
Divide and conquer
Christian Steiner / pixelio.de
Basti
• Sebastian Springer
• from Munich
• work @ MaibornWolff GmbH
• https://github.com/sspringer82
• @basti_springer
• JavaScript Developer
Agenda
HTTP Microservice with Express
• Routing
• Structure
• Database
• Logging
• Tests
• Container
Commandbased Microservices with
Seneca
• Patterns
• Plugins
• Queueing
Rainer Sturm / pixelio.de
Microservices
Small
Scaleable
Resilient
Independent Testable
Focused
JavaScript is nearly everywhere.
There are a lot of OSS Modules.
Node.js was built for the web
Node.js supports most of the protocols, systems and
databases.
The platform is lightweight.
Example
A microservice that delivers articles for a web shop.
M. Hermsdorf / pixelio.de
Webshop
Client API
Articles
Payment
Users
DB
DB
DB
Auth
Logger
List of articles
Router
Controller
Model
Datenbank
Logger
Packages
S. Hofschlaeger / pixelio.de
Express.js
Express is a lightweight (< 2MB) web application framework
for Node.js.
Express supports HTTP and HTTPS in version 1 and 2.
Express handles routing within a web application for you.
Additionally it provides you with a plugin interface
(Middleware).
Installation
yarn init
yarn add express
Structure of a Microservice
.
├── db
│   ├── config.js
│   └── db.sqlite3
├── package.json
├── spec
└── src
   ├── config.js
   ├── controller.js
   ├── index.js
   ├── logger.js
   ├── model.js
   └── router.js
Entry point
index.js
Entry point
const express = require('express');
const router = require('./router');
const app = express();
router(app);
app.listen(8080, () => {
console.log('Service is listening to http://localhost:
8080');
});
Entry point
In this file all global packages are included and the app is
configured.
Additional features should be put in separate files.
Router
router.js
Router
const controller = require('./controller');
module.exports = (app) => {
app.get('/article', controller.getAll);
app.get('/article/:id', controller.getOne);
app.post('/article', controller.create);
app.put('/article', controller.update);
app.delete('/article', controller.remove);
}
Router
The router defines all available routes of a microservice.
A route consists of a HTTP method and a path. By adding
variables to routes they become more flexible.
To keep the code of your router readable, you should put the
routing callbacks in a separate file.
Controller
controller.js
Controller
const model = require('./model');
module.exports = {
getAll(req, res) {
res.json(
model.getAll()
);
},
getOne(req, res) {},
create(req, res) {},
update(req, res) {},
remove(req, res) {}
}
Controller
The controller holds your routing callback functions. It
extracts information from the requests and hands the
information over to the model.
To access variables of your routes, you can use the
req.params object.
To deal with information within the request body, you should
install the body-parser middleware. It introduces the req.body
object which represents the message body.
Model
model.js
Model
The model contains the business logic of your application. It
also controls access to the database.
Usually every microservice has its own database, which
increases independence between services.
Model
Node.js supports all common databases such as OracleDB,
MySQL, Redis, MongoDB.
To access your database, you have to install a database driver
first.
yarn add sqlite3
To further simplify the access, you can use various ORMs or
ODMs
yarn add orm
ORM
An ORM handles CRUD operations for you. It already
implements all common use cases. You just have to
configure it with the structure of your database.
The ORM also takes care of some security features such as
escaping.
ORM
const express = require('express');
const orm = require('orm');
const router = require('./router');
const dbConfig = require('./db/config.js');
const {dbPath} = require('./config.js');
const app = express();
app.use(orm.express(dbPath, dbConfig));
router(app);
app.listen(8080, () => {
console.log('Service is listening to http://localhost:
8080');
});
ORM
module.exports = {
define(db, models, next) {
models.articles = db.define('articles', {
id: Number,
title: String,
price: Number
});
next();
}
}
Model
Besides encapsulating database communication your model
takes care of additional tasks such as validation of user input
and various calculations.
Most of these operations are asynchronous. To provide a
clean API you should think about using promises, async
functions or streams instead of plain callbacks.
async getAll(req, res) {
try {
const articles = await model.getAll(req);
res.json(articles);
} catch (e) {
res.status(500).send(e);
}
}
getAll(req) {
return new Promise((resolve, reject) => {
req.models.articles.all((err, results) => {
if (err) {
reject(err);
} else {
resolve(results);
}
});
});
}
controller
model
Logging
Tim Reckmann / pixelio.de
Logging
Within your microservice errors might occur at any time. Of
course you should be prepared to catch and handle them.
But you should also keep a log of errors somewhere.
A logger should not be a fixed part of a certain microservice.
logging is a shared service which is available for all services
in your application.
Centralised logging provides some advantages over local
logging such as scalability and an improved maintainability.
Logging
You can use log4js for remote logging in your application.
This library provides a plugin interface for external appenders
which support various log targets such as files or logstash.
For remote logging you could use the logstash appender and
a centralised logstash server.
Logging
const log4js = require('log4js');
log4js.configure({
appenders: [{
"host": "127.0.0.1",
"port": 10001,
"type": "logstashUDP",
"logType": "database",
"layout": {
"type": "pattern",
"pattern": "%m"
},
"category": "database"
}],
categories: { default: { appenders: ['database'], level:
'error' } }
});
module.exports = log4js;
Logging
const log4js = require('./logger');
module.exports = {
getAll(req) {
return new Promise((resolve, reject) => {
req.models.articles.all((err, results) => {
if (err) {
reject(err);
log4js.getLogger('database').error(err);
} else {
resolve(results);
}
});
});
}
}
Tests
Dieter Schütz / pixelio.de
Tests
Quality and stability are two very important aspects of
microservices. To ensure this, you need the ability to
automatically test your services.
There are two levels of tests for your microservice application:
unittests for smaller units of code and integration tests for
external interfaces.
For unittests you can use Jasmine as a framework. With
Frisby.js you can test your interfaces.
Unittests
yarn add jasmine
node_modules/.bin/jasmine init
Unittests
const model = require('../model');
describe('model', () => {
it('should handle a database error correctly', () => {
const req = {
models: {
articles: {
all: (cb) => {cb('error', null);}
}
}
}
model.getAll(req).catch((e) => {
expect(e).toBe('error');
});
})
});
Unittests
To execute your tests, just issue the command npx jasmine.
You have two variants for organising your tests. You can either
store them in a separate directory, usually named “spec” or
you put your tests where your source code is located.
Mockery
In your microservice application you have to deal with a lot of
dependencies. They are resolved via the node module
system. Mockery is a tool that helps you with dealing with
dependencies. Mockery replaces libraries with test doubles.
yarn add -D mockery
Mockery
const mockery = require('mockery');
beforeEach(() => {
mockery.enable();
const fsMock = {
stat: function (path, cb) {...}
};
mockery.registerMock('fs', fsMock);
});
afterEach(() => {
mockery.disable();
});
Integration tests
Frisby.js is a library for testing REST interfaces. Frisby is an
extension for Jasmine. So you don’t have to learn an additonal
technology.
In order to run Frisby.js, you have to install jasmine-node.
yarn add -D frisby jasmine-node
Integration tests
require('jasmine-core');
var frisby = require('frisby');
frisby.create('Get all the articles')
.get('http://localhost:8080/article')
.expectStatus(200)
.expectHeaderContains('content-type', 'application/json')
.expectJSON('0', {
id: function (val) { expect(val).toBe(1);},
title: 'Mannesmann Schlosserhammer',
price: 7
})
.toss();
PM2
Node.js is single threaded. Basically that’s not a problem
because of its nonblocking I/O nature. To optimally use all
available resources, you can use the child_process module.
A more convenient way of locally scaling your application is
using PM2.
yarn add pm2
PM2
pm2 start app.js
pm2 start app.js -i 4
pm2 reload all
pm2 scale <app-name> 10
pm2 list
pm2 stop
pm2 delete
Docker
All your services run in independent, self contained
containers.
You can start as many instances of a certain container as you
need.
To extend the features of your application, you simply add
additional services by starting containers.
Dockerfile
FROM node:7.10
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN yarn install
# Bundle app source
COPY . /usr/src/app
EXPOSE 8080
CMD [ "yarn", "start" ]
Docker
docker build -t basti/microservice .
docker run -p 8080:8080 -d basti/microservice
API Gateway
Jürgen Reitböck / pixelio.de
API Gateway
Each service of your application has to focus on its purpose.
In order to accomplish this, you have to centralise certain
services. A typical example for a central service is
authentication.
An API Gateway forwards authorised requests to the services
of your application, receives the answers and forwards them to
the client.
Seneca
Seneca follows a completely different approach. All services
of your application communicate via messages and become
independent of the transport layer.
Installation
yarn add seneca
Service Definition
const seneca = require('seneca')();
seneca.add({role: 'math', cmd: 'sum'}, controller.getAll);
The first argument of the add method is the pattern, which
describes the service. You are free to define the pattern as
you want. A common best practice is to define a role and a
command. The second argument is an action, a function that
handles incoming requests.
Service Handler
async getAll(msg, reply) {
try {
const articles = await model.getAll(req);
reply(null, JSON.stringify(articles));
} catch (e) {
reply(e);
}
}
Similar to express a service handler receives the
representation of a request. It also gets a reply function. To
create a response, you call the reply function with an error
object and the response body.
Service Call
seneca.act({role: 'article', cmd: 'get'}, (err, result) => {
if (err) {
return console.error(err);
}
console.log(result);
});
With seneca.act you consume a microservice. You supply the
object representation of a message and a callback function.
With the object, you trigger the service. As soon as the answer
of the service is available, the callback is executed.
Patterns
Helmut / pixelio.deHelmut / pixelio.de
Patterns
You can create multiple patterns of the same type. If a
service call matches multiple patterns, the most specific is
used.
You can use this behaviour to implement versioning of
interfaces.
Plugins
Klicker / pixelio.de
Plugins
A plugin is a collection of patterns. There are multiple
sources of plugins: built-in, your own plugins and 3rd party
plugins.
Plugins are used for logging or debugging.
Plugins
You organise your patterns with the use method.
The name of the function is used for logging purposes.
You can pass options to your plugin to further configure it.
The init pattern is used instead of a constructor.
const seneca = require('seneca')();
function articles(options) {
this.add({role:'article',cmd:'get'}, controller.getAll);
}
seneca.use(articles);
Plugins
const seneca = require('seneca')();
function articles(options) {
this.add({role:'article',cmd:'get'}, controller.getAll);
this.wrap({role:'article'}, controller.verify);
}
seneca.use(articles);
The wrap method defines features that are used by multiple
patterns. With this.prior(msg, respond) the original service
can be called.
Client/Server
cre8tive / pixelio.de
Server
function articles(options) {
this.add({role:'article',cmd:'get'}, controller.getAll);
this.wrap({role:'article'}, controller.verify);
}
require('seneca')()
.use(articles)
.listen(8080)
Just like in the ordinary web server the listen method binds
the server to the port 8080. Your service can then be called by
the browser or another server:
http://localhost:8080/act?role=article&cmd=get
Client
require('seneca')()
.client(8080)
.act({role: 'article', cmd: 'get'}, console.log);
The client method lets you connect to a seneca microservice.
Change the transport
// client
seneca.client({
type: 'tcp',
port: 8080
});
// server
seneca.listen({
type: 'tcp',
port: 8080
});
By providing the type ‘tcp’ the TCP protocol is used instead of
HTTP as a communication protocol.
Integration in Express
Integration in Express
const SenecaWeb = require('seneca-web');
const Express = require('express');
const router = new Express.Router();
const seneca = require('seneca')();
const app = Express();
const senecaWebConfig = {
context: router,
adapter: require('seneca-web-adapter-express'),
options: { parseBody: false }
}
app.use( require('body-parser').json() )
.use( router )
.listen(8080);
seneca.use(SenecaWeb, senecaWebConfig )
.use('api')
.client( { type:'tcp', pin:'role:article' } );
Integration in Express
With this configuration seneca adds routes to your Express
application.
You have to adopt your seneca patterns a little bit. All routes
defined with seneca.act('role:web', {routes: routes}) are added
as Express routes.
Via the path-pattern a corresponding matching is done.
Communication via a
queue
S. Hofschlaeger / pixelio.de
Queue
You can use various 3rd party plugins to communicate via a
message queue instead of sending messages over network.
The main advantage of using a Queue is decoupling client
and server. Your system becomes more robust.
Queue
yarn add seneca-servicebus-transport
Queue
require('seneca')()
.use('seneca-servicebus-transport')
.use(articles)
.listen({
type: 'servicebus',
connection_string: '...'
});
require('seneca')()
.use('seneca-servicebus-transport')
.client({
type: 'servicebus',
connection_string: '...'
})
.act({role: 'article', cmd: 'get'}, console.log);
Server
Client
Microservices, the silver
bullet?
Microservices might be a good solution for certain problems
but definitely not for all problems in web development.
Microservices introduce an increased complexity to your
application. There is a lot of Node.js packages dealing with
this problem. Some of these packages are outdated or of bad
quality.
Take a look at GitHub statistics and npmjs.com if it fits your
needs.
Questions
Rainer Sturm / pixelio.de
CONTACT
Sebastian Springer
sebastian.springer@maibornwolff.de
MaibornWolff GmbH
Theresienhöhe 13
80339 München
@basti_springer
https://github.com/sspringer82

More Related Content

What's hot

Introduction to Node js
Introduction to Node jsIntroduction to Node js
Introduction to Node jsAkshay Mathur
 
Kraken js at paypal
Kraken js at paypalKraken js at paypal
Kraken js at paypalLenny Markus
 
Intro to node and non blocking io
Intro to node and non blocking ioIntro to node and non blocking io
Intro to node and non blocking ioAmy Hua
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.jsjacekbecela
 
Java script at backend nodejs
Java script at backend   nodejsJava script at backend   nodejs
Java script at backend nodejsAmit Thakkar
 
Intro to Node.js (v1)
Intro to Node.js (v1)Intro to Node.js (v1)
Intro to Node.js (v1)Chris Cowan
 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.jsVikash Singh
 
Agile JavaScript Testing
Agile JavaScript TestingAgile JavaScript Testing
Agile JavaScript TestingScott Becker
 
Real-Time Web Apps & Symfony. What are your options?
Real-Time Web Apps & Symfony. What are your options?Real-Time Web Apps & Symfony. What are your options?
Real-Time Web Apps & Symfony. What are your options?Phil Leggetter
 
NodeJS - Server Side JS
NodeJS - Server Side JS NodeJS - Server Side JS
NodeJS - Server Side JS Ganesh Kondal
 
Introduction to Python Celery
Introduction to Python CeleryIntroduction to Python Celery
Introduction to Python CeleryMahendra M
 
Play Framework: async I/O with Java and Scala
Play Framework: async I/O with Java and ScalaPlay Framework: async I/O with Java and Scala
Play Framework: async I/O with Java and ScalaYevgeniy Brikman
 
[212] large scale backend service develpment
[212] large scale backend service develpment[212] large scale backend service develpment
[212] large scale backend service develpmentNAVER D2
 
Performance and Scalability Testing with Python and Multi-Mechanize
Performance and Scalability Testing with Python and Multi-MechanizePerformance and Scalability Testing with Python and Multi-Mechanize
Performance and Scalability Testing with Python and Multi-Mechanizecoreygoldberg
 
[1D1]신개념 N스크린 웹 앱 프레임워크 PARS
[1D1]신개념 N스크린 웹 앱 프레임워크 PARS[1D1]신개념 N스크린 웹 앱 프레임워크 PARS
[1D1]신개념 N스크린 웹 앱 프레임워크 PARSNAVER D2
 
Rapid scaling in_the_cloud_with_puppet
Rapid scaling in_the_cloud_with_puppetRapid scaling in_the_cloud_with_puppet
Rapid scaling in_the_cloud_with_puppetCarl Caum
 

What's hot (20)

Introduction to Node js
Introduction to Node jsIntroduction to Node js
Introduction to Node js
 
Kraken js at paypal
Kraken js at paypalKraken js at paypal
Kraken js at paypal
 
Intro to node and non blocking io
Intro to node and non blocking ioIntro to node and non blocking io
Intro to node and non blocking io
 
Introduction to node.js
Introduction to node.jsIntroduction to node.js
Introduction to node.js
 
Java script at backend nodejs
Java script at backend   nodejsJava script at backend   nodejs
Java script at backend nodejs
 
Intro to Node.js (v1)
Intro to Node.js (v1)Intro to Node.js (v1)
Intro to Node.js (v1)
 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.js
 
Agile JavaScript Testing
Agile JavaScript TestingAgile JavaScript Testing
Agile JavaScript Testing
 
Real-Time Web Apps & Symfony. What are your options?
Real-Time Web Apps & Symfony. What are your options?Real-Time Web Apps & Symfony. What are your options?
Real-Time Web Apps & Symfony. What are your options?
 
OHHttpStubs
OHHttpStubsOHHttpStubs
OHHttpStubs
 
NodeJS - Server Side JS
NodeJS - Server Side JS NodeJS - Server Side JS
NodeJS - Server Side JS
 
Celery with python
Celery with pythonCelery with python
Celery with python
 
Introduction to Python Celery
Introduction to Python CeleryIntroduction to Python Celery
Introduction to Python Celery
 
Play Framework: async I/O with Java and Scala
Play Framework: async I/O with Java and ScalaPlay Framework: async I/O with Java and Scala
Play Framework: async I/O with Java and Scala
 
Nodejs intro
Nodejs introNodejs intro
Nodejs intro
 
Node js introduction
Node js introductionNode js introduction
Node js introduction
 
[212] large scale backend service develpment
[212] large scale backend service develpment[212] large scale backend service develpment
[212] large scale backend service develpment
 
Performance and Scalability Testing with Python and Multi-Mechanize
Performance and Scalability Testing with Python and Multi-MechanizePerformance and Scalability Testing with Python and Multi-Mechanize
Performance and Scalability Testing with Python and Multi-Mechanize
 
[1D1]신개념 N스크린 웹 앱 프레임워크 PARS
[1D1]신개념 N스크린 웹 앱 프레임워크 PARS[1D1]신개념 N스크린 웹 앱 프레임워크 PARS
[1D1]신개념 N스크린 웹 앱 프레임워크 PARS
 
Rapid scaling in_the_cloud_with_puppet
Rapid scaling in_the_cloud_with_puppetRapid scaling in_the_cloud_with_puppet
Rapid scaling in_the_cloud_with_puppet
 

Similar to Divide and Conquer Microservices

Devfest 2023 - Service Weaver Introduction - Taipei.pdf
Devfest 2023 - Service Weaver Introduction - Taipei.pdfDevfest 2023 - Service Weaver Introduction - Taipei.pdf
Devfest 2023 - Service Weaver Introduction - Taipei.pdfKAI CHU CHUNG
 
RESTful API In Node Js using Express
RESTful API In Node Js using Express RESTful API In Node Js using Express
RESTful API In Node Js using Express Jeetendra singh
 
Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...
Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...
Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...Codemotion
 
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
 
Web services in java
Web services in javaWeb services in java
Web services in javamaabujji
 
Day in a life of a node.js developer
Day in a life of a node.js developerDay in a life of a node.js developer
Day in a life of a node.js developerEdureka!
 
Day In A Life Of A Node.js Developer
Day In A Life Of A Node.js DeveloperDay In A Life Of A Node.js Developer
Day In A Life Of A Node.js DeveloperEdureka!
 
NodeJS guide for beginners
NodeJS guide for beginnersNodeJS guide for beginners
NodeJS guide for beginnersEnoch Joshua
 
Apache Samza 1.0 - What's New, What's Next
Apache Samza 1.0 - What's New, What's NextApache Samza 1.0 - What's New, What's Next
Apache Samza 1.0 - What's New, What's NextPrateek Maheshwari
 
540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdf540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdfhamzadamani7
 
RAHUL_Updated( (2)
RAHUL_Updated( (2)RAHUL_Updated( (2)
RAHUL_Updated( (2)Rahul Singh
 
AWS Webcast - Build Agile Applications in AWS Cloud for Government
AWS Webcast - Build Agile Applications in AWS Cloud for GovernmentAWS Webcast - Build Agile Applications in AWS Cloud for Government
AWS Webcast - Build Agile Applications in AWS Cloud for GovernmentAmazon Web Services
 
Flex 4.5 jeyasekar
Flex 4.5  jeyasekarFlex 4.5  jeyasekar
Flex 4.5 jeyasekarjeya soft
 
Using Apache as an Application Server
Using Apache as an Application ServerUsing Apache as an Application Server
Using Apache as an Application ServerPhil Windley
 

Similar to Divide and Conquer Microservices (20)

NodeJS @ ACS
NodeJS @ ACSNodeJS @ ACS
NodeJS @ ACS
 
Devfest 2023 - Service Weaver Introduction - Taipei.pdf
Devfest 2023 - Service Weaver Introduction - Taipei.pdfDevfest 2023 - Service Weaver Introduction - Taipei.pdf
Devfest 2023 - Service Weaver Introduction - Taipei.pdf
 
Express node js
Express node jsExpress node js
Express node js
 
RESTful API In Node Js using Express
RESTful API In Node Js using Express RESTful API In Node Js using Express
RESTful API In Node Js using Express
 
Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...
Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...
Alberto Maria Angelo Paro - Isomorphic programming in Scala and WebDevelopmen...
 
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)
 
Web services in java
Web services in javaWeb services in java
Web services in java
 
Day in a life of a node.js developer
Day in a life of a node.js developerDay in a life of a node.js developer
Day in a life of a node.js developer
 
Day In A Life Of A Node.js Developer
Day In A Life Of A Node.js DeveloperDay In A Life Of A Node.js Developer
Day In A Life Of A Node.js Developer
 
Node js
Node jsNode js
Node js
 
NodeJS guide for beginners
NodeJS guide for beginnersNodeJS guide for beginners
NodeJS guide for beginners
 
NodeJS for Beginner
NodeJS for BeginnerNodeJS for Beginner
NodeJS for Beginner
 
Apache Samza 1.0 - What's New, What's Next
Apache Samza 1.0 - What's New, What's NextApache Samza 1.0 - What's New, What's Next
Apache Samza 1.0 - What's New, What's Next
 
540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdf540slidesofnodejsbackendhopeitworkforu.pdf
540slidesofnodejsbackendhopeitworkforu.pdf
 
RAHUL_Updated( (2)
RAHUL_Updated( (2)RAHUL_Updated( (2)
RAHUL_Updated( (2)
 
Mean stack Magics
Mean stack MagicsMean stack Magics
Mean stack Magics
 
node.js.pptx
node.js.pptxnode.js.pptx
node.js.pptx
 
AWS Webcast - Build Agile Applications in AWS Cloud for Government
AWS Webcast - Build Agile Applications in AWS Cloud for GovernmentAWS Webcast - Build Agile Applications in AWS Cloud for Government
AWS Webcast - Build Agile Applications in AWS Cloud for Government
 
Flex 4.5 jeyasekar
Flex 4.5  jeyasekarFlex 4.5  jeyasekar
Flex 4.5 jeyasekar
 
Using Apache as an Application Server
Using Apache as an Application ServerUsing Apache as an Application Server
Using Apache as an Application Server
 

More from Sebastian Springer (20)

Schnelleinstieg in Angular
Schnelleinstieg in AngularSchnelleinstieg in Angular
Schnelleinstieg in Angular
 
Von 0 auf 100 - Performance im Web
Von 0 auf 100 - Performance im WebVon 0 auf 100 - Performance im Web
Von 0 auf 100 - Performance im Web
 
A/B Testing mit Node.js
A/B Testing mit Node.jsA/B Testing mit Node.js
A/B Testing mit Node.js
 
Angular2
Angular2Angular2
Angular2
 
Einführung in React
Einführung in ReactEinführung in React
Einführung in React
 
JavaScript Performance
JavaScript PerformanceJavaScript Performance
JavaScript Performance
 
ECMAScript 6 im Produktivbetrieb
ECMAScript 6 im ProduktivbetriebECMAScript 6 im Produktivbetrieb
ECMAScript 6 im Produktivbetrieb
 
Streams in Node.js
Streams in Node.jsStreams in Node.js
Streams in Node.js
 
JavaScript Performance
JavaScript PerformanceJavaScript Performance
JavaScript Performance
 
Große Applikationen mit AngularJS
Große Applikationen mit AngularJSGroße Applikationen mit AngularJS
Große Applikationen mit AngularJS
 
Testing tools
Testing toolsTesting tools
Testing tools
 
Node.js Security
Node.js SecurityNode.js Security
Node.js Security
 
Typescript
TypescriptTypescript
Typescript
 
Reactive Programming
Reactive ProgrammingReactive Programming
Reactive Programming
 
Best Practices für TDD in JavaScript
Best Practices für TDD in JavaScriptBest Practices für TDD in JavaScript
Best Practices für TDD in JavaScript
 
Warum ECMAScript 6 die Welt ein Stückchen besser macht
Warum ECMAScript 6 die Welt ein Stückchen besser machtWarum ECMAScript 6 die Welt ein Stückchen besser macht
Warum ECMAScript 6 die Welt ein Stückchen besser macht
 
Lean Startup mit JavaScript
Lean Startup mit JavaScriptLean Startup mit JavaScript
Lean Startup mit JavaScript
 
Webapplikationen mit Node.js
Webapplikationen mit Node.jsWebapplikationen mit Node.js
Webapplikationen mit Node.js
 
Node.js für Webapplikationen
Node.js für WebapplikationenNode.js für Webapplikationen
Node.js für Webapplikationen
 
Debugging und Profiling
Debugging und ProfilingDebugging und Profiling
Debugging und Profiling
 

Recently uploaded

Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 

Recently uploaded (20)

Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 

Divide and Conquer Microservices

  • 1. Divide and conquer Christian Steiner / pixelio.de
  • 2.
  • 3. Basti • Sebastian Springer • from Munich • work @ MaibornWolff GmbH • https://github.com/sspringer82 • @basti_springer • JavaScript Developer
  • 4.
  • 5. Agenda HTTP Microservice with Express • Routing • Structure • Database • Logging • Tests • Container Commandbased Microservices with Seneca • Patterns • Plugins • Queueing Rainer Sturm / pixelio.de
  • 7. JavaScript is nearly everywhere. There are a lot of OSS Modules. Node.js was built for the web Node.js supports most of the protocols, systems and databases. The platform is lightweight.
  • 8. Example A microservice that delivers articles for a web shop. M. Hermsdorf / pixelio.de
  • 12.
  • 13. Express.js Express is a lightweight (< 2MB) web application framework for Node.js. Express supports HTTP and HTTPS in version 1 and 2. Express handles routing within a web application for you. Additionally it provides you with a plugin interface (Middleware).
  • 15. Structure of a Microservice . ├── db │   ├── config.js │   └── db.sqlite3 ├── package.json ├── spec └── src    ├── config.js    ├── controller.js    ├── index.js    ├── logger.js    ├── model.js    └── router.js
  • 17. Entry point const express = require('express'); const router = require('./router'); const app = express(); router(app); app.listen(8080, () => { console.log('Service is listening to http://localhost: 8080'); });
  • 18. Entry point In this file all global packages are included and the app is configured. Additional features should be put in separate files.
  • 20. Router const controller = require('./controller'); module.exports = (app) => { app.get('/article', controller.getAll); app.get('/article/:id', controller.getOne); app.post('/article', controller.create); app.put('/article', controller.update); app.delete('/article', controller.remove); }
  • 21. Router The router defines all available routes of a microservice. A route consists of a HTTP method and a path. By adding variables to routes they become more flexible. To keep the code of your router readable, you should put the routing callbacks in a separate file.
  • 23. Controller const model = require('./model'); module.exports = { getAll(req, res) { res.json( model.getAll() ); }, getOne(req, res) {}, create(req, res) {}, update(req, res) {}, remove(req, res) {} }
  • 24. Controller The controller holds your routing callback functions. It extracts information from the requests and hands the information over to the model. To access variables of your routes, you can use the req.params object. To deal with information within the request body, you should install the body-parser middleware. It introduces the req.body object which represents the message body.
  • 26. Model The model contains the business logic of your application. It also controls access to the database. Usually every microservice has its own database, which increases independence between services.
  • 27. Model Node.js supports all common databases such as OracleDB, MySQL, Redis, MongoDB. To access your database, you have to install a database driver first. yarn add sqlite3 To further simplify the access, you can use various ORMs or ODMs yarn add orm
  • 28. ORM An ORM handles CRUD operations for you. It already implements all common use cases. You just have to configure it with the structure of your database. The ORM also takes care of some security features such as escaping.
  • 29. ORM const express = require('express'); const orm = require('orm'); const router = require('./router'); const dbConfig = require('./db/config.js'); const {dbPath} = require('./config.js'); const app = express(); app.use(orm.express(dbPath, dbConfig)); router(app); app.listen(8080, () => { console.log('Service is listening to http://localhost: 8080'); });
  • 30. ORM module.exports = { define(db, models, next) { models.articles = db.define('articles', { id: Number, title: String, price: Number }); next(); } }
  • 31. Model Besides encapsulating database communication your model takes care of additional tasks such as validation of user input and various calculations. Most of these operations are asynchronous. To provide a clean API you should think about using promises, async functions or streams instead of plain callbacks.
  • 32. async getAll(req, res) { try { const articles = await model.getAll(req); res.json(articles); } catch (e) { res.status(500).send(e); } } getAll(req) { return new Promise((resolve, reject) => { req.models.articles.all((err, results) => { if (err) { reject(err); } else { resolve(results); } }); }); } controller model
  • 34. Logging Within your microservice errors might occur at any time. Of course you should be prepared to catch and handle them. But you should also keep a log of errors somewhere. A logger should not be a fixed part of a certain microservice. logging is a shared service which is available for all services in your application. Centralised logging provides some advantages over local logging such as scalability and an improved maintainability.
  • 35. Logging You can use log4js for remote logging in your application. This library provides a plugin interface for external appenders which support various log targets such as files or logstash. For remote logging you could use the logstash appender and a centralised logstash server.
  • 36. Logging const log4js = require('log4js'); log4js.configure({ appenders: [{ "host": "127.0.0.1", "port": 10001, "type": "logstashUDP", "logType": "database", "layout": { "type": "pattern", "pattern": "%m" }, "category": "database" }], categories: { default: { appenders: ['database'], level: 'error' } } }); module.exports = log4js;
  • 37. Logging const log4js = require('./logger'); module.exports = { getAll(req) { return new Promise((resolve, reject) => { req.models.articles.all((err, results) => { if (err) { reject(err); log4js.getLogger('database').error(err); } else { resolve(results); } }); }); } }
  • 39. Tests Quality and stability are two very important aspects of microservices. To ensure this, you need the ability to automatically test your services. There are two levels of tests for your microservice application: unittests for smaller units of code and integration tests for external interfaces. For unittests you can use Jasmine as a framework. With Frisby.js you can test your interfaces.
  • 41. Unittests const model = require('../model'); describe('model', () => { it('should handle a database error correctly', () => { const req = { models: { articles: { all: (cb) => {cb('error', null);} } } } model.getAll(req).catch((e) => { expect(e).toBe('error'); }); }) });
  • 42. Unittests To execute your tests, just issue the command npx jasmine. You have two variants for organising your tests. You can either store them in a separate directory, usually named “spec” or you put your tests where your source code is located.
  • 43. Mockery In your microservice application you have to deal with a lot of dependencies. They are resolved via the node module system. Mockery is a tool that helps you with dealing with dependencies. Mockery replaces libraries with test doubles. yarn add -D mockery
  • 44. Mockery const mockery = require('mockery'); beforeEach(() => { mockery.enable(); const fsMock = { stat: function (path, cb) {...} }; mockery.registerMock('fs', fsMock); }); afterEach(() => { mockery.disable(); });
  • 45. Integration tests Frisby.js is a library for testing REST interfaces. Frisby is an extension for Jasmine. So you don’t have to learn an additonal technology. In order to run Frisby.js, you have to install jasmine-node. yarn add -D frisby jasmine-node
  • 46. Integration tests require('jasmine-core'); var frisby = require('frisby'); frisby.create('Get all the articles') .get('http://localhost:8080/article') .expectStatus(200) .expectHeaderContains('content-type', 'application/json') .expectJSON('0', { id: function (val) { expect(val).toBe(1);}, title: 'Mannesmann Schlosserhammer', price: 7 }) .toss();
  • 47.
  • 48. PM2 Node.js is single threaded. Basically that’s not a problem because of its nonblocking I/O nature. To optimally use all available resources, you can use the child_process module. A more convenient way of locally scaling your application is using PM2. yarn add pm2
  • 49. PM2 pm2 start app.js pm2 start app.js -i 4 pm2 reload all pm2 scale <app-name> 10 pm2 list pm2 stop pm2 delete
  • 50.
  • 51. Docker All your services run in independent, self contained containers. You can start as many instances of a certain container as you need. To extend the features of your application, you simply add additional services by starting containers.
  • 52. Dockerfile FROM node:7.10 # Create app directory RUN mkdir -p /usr/src/app WORKDIR /usr/src/app # Install app dependencies COPY package.json /usr/src/app/ RUN yarn install # Bundle app source COPY . /usr/src/app EXPOSE 8080 CMD [ "yarn", "start" ]
  • 53. Docker docker build -t basti/microservice . docker run -p 8080:8080 -d basti/microservice
  • 55. API Gateway Each service of your application has to focus on its purpose. In order to accomplish this, you have to centralise certain services. A typical example for a central service is authentication. An API Gateway forwards authorised requests to the services of your application, receives the answers and forwards them to the client.
  • 56.
  • 57. Seneca Seneca follows a completely different approach. All services of your application communicate via messages and become independent of the transport layer.
  • 59. Service Definition const seneca = require('seneca')(); seneca.add({role: 'math', cmd: 'sum'}, controller.getAll); The first argument of the add method is the pattern, which describes the service. You are free to define the pattern as you want. A common best practice is to define a role and a command. The second argument is an action, a function that handles incoming requests.
  • 60. Service Handler async getAll(msg, reply) { try { const articles = await model.getAll(req); reply(null, JSON.stringify(articles)); } catch (e) { reply(e); } } Similar to express a service handler receives the representation of a request. It also gets a reply function. To create a response, you call the reply function with an error object and the response body.
  • 61. Service Call seneca.act({role: 'article', cmd: 'get'}, (err, result) => { if (err) { return console.error(err); } console.log(result); }); With seneca.act you consume a microservice. You supply the object representation of a message and a callback function. With the object, you trigger the service. As soon as the answer of the service is available, the callback is executed.
  • 63. Patterns You can create multiple patterns of the same type. If a service call matches multiple patterns, the most specific is used. You can use this behaviour to implement versioning of interfaces.
  • 65. Plugins A plugin is a collection of patterns. There are multiple sources of plugins: built-in, your own plugins and 3rd party plugins. Plugins are used for logging or debugging.
  • 66. Plugins You organise your patterns with the use method. The name of the function is used for logging purposes. You can pass options to your plugin to further configure it. The init pattern is used instead of a constructor. const seneca = require('seneca')(); function articles(options) { this.add({role:'article',cmd:'get'}, controller.getAll); } seneca.use(articles);
  • 67. Plugins const seneca = require('seneca')(); function articles(options) { this.add({role:'article',cmd:'get'}, controller.getAll); this.wrap({role:'article'}, controller.verify); } seneca.use(articles); The wrap method defines features that are used by multiple patterns. With this.prior(msg, respond) the original service can be called.
  • 69. Server function articles(options) { this.add({role:'article',cmd:'get'}, controller.getAll); this.wrap({role:'article'}, controller.verify); } require('seneca')() .use(articles) .listen(8080) Just like in the ordinary web server the listen method binds the server to the port 8080. Your service can then be called by the browser or another server: http://localhost:8080/act?role=article&cmd=get
  • 70. Client require('seneca')() .client(8080) .act({role: 'article', cmd: 'get'}, console.log); The client method lets you connect to a seneca microservice.
  • 71. Change the transport // client seneca.client({ type: 'tcp', port: 8080 }); // server seneca.listen({ type: 'tcp', port: 8080 }); By providing the type ‘tcp’ the TCP protocol is used instead of HTTP as a communication protocol.
  • 73. Integration in Express const SenecaWeb = require('seneca-web'); const Express = require('express'); const router = new Express.Router(); const seneca = require('seneca')(); const app = Express(); const senecaWebConfig = { context: router, adapter: require('seneca-web-adapter-express'), options: { parseBody: false } } app.use( require('body-parser').json() ) .use( router ) .listen(8080); seneca.use(SenecaWeb, senecaWebConfig ) .use('api') .client( { type:'tcp', pin:'role:article' } );
  • 74. Integration in Express With this configuration seneca adds routes to your Express application. You have to adopt your seneca patterns a little bit. All routes defined with seneca.act('role:web', {routes: routes}) are added as Express routes. Via the path-pattern a corresponding matching is done.
  • 75. Communication via a queue S. Hofschlaeger / pixelio.de
  • 76. Queue You can use various 3rd party plugins to communicate via a message queue instead of sending messages over network. The main advantage of using a Queue is decoupling client and server. Your system becomes more robust.
  • 79. Microservices, the silver bullet? Microservices might be a good solution for certain problems but definitely not for all problems in web development. Microservices introduce an increased complexity to your application. There is a lot of Node.js packages dealing with this problem. Some of these packages are outdated or of bad quality. Take a look at GitHub statistics and npmjs.com if it fits your needs.
  • 81. CONTACT Sebastian Springer sebastian.springer@maibornwolff.de MaibornWolff GmbH Theresienhöhe 13 80339 München @basti_springer https://github.com/sspringer82