SlideShare a Scribd company logo
1 of 65
Download to read offline
(MICRO?) SERVICES
ARCHITECTURE IN PRACTICE
ADAM POLAK
HEAD OF NODE.JS
ADAM.POLAK@TSH.IO
POLAK.ADAM1
THEORY
▸ SPECIALIZED SMALL APPS
▸ SEPARATE REPOS
▸ OWN STRUCTURE, API AND LANGUAGE
▸ INDEPENDENT BUILDS, TESTS AND DEPLOYS
▸ EASY TO MAINTAIN BECAUSE OF SMALL CODE
BASE
THEORY
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
A BRAND NEW
PROJECT
▸ 5 SERVICES AT START
▸ SPA
▸ 6-7 DEVELOPERS AT START
PROJECT
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
▸ WHAT ABOUT REPOSITORIES?
▸ WHAT ABOUT API?
▸ WHAT ABOUT SETTING UP NEW SERVICE?
▸ WHAT ABOUT DEVELOPMENT?
▸ WHAT ABOUT TESTS?
▸ AND MANY MANY MORE
QUESTIONS?
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
MULTIPLE
REPOSITORIES
SPA API
Frontend Backend
USE CASE #1
USE CASE SUMARY
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
▸ 2 “SERVICES” - SPA + API
▸ SEPARATE TEAMS
▸ DIFFERENT PROJECT STRUCTURE
▸ TECH PER PROJECT
▸ PRACTICES PER PROJECT
LET’S SCALE
IT UP!
GATEWAY
PAYMENT
USE CASE #2 - BACKEND
REPORTINGSECURITYSEARCH
USE CASE #2 - FRONTEND
SPA GATEWAY
THEORY VS REALITY
GATEWAY
NODE.JS
1 DEV
SECURITY
PHP
1 DEV
REPORTING
PHP
1 DEV
PAYMENT
.NET
1 DEV
SEARCH
PYTHON
1 DEV
SPA
REACT
1 DEV
THEORY
▸ BEST AVAILABLE TECH FOR GIVEN TASK
▸ ???
PROS
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
▸ 6 DIFFERENT TECH STACKS
▸ NO SHARED CODE = DUPLICATION
▸ 6 DIFFERENT BUILD/DEPLOY PROCESSES
▸ MUCH HARDER TO MOVE DEVS BETWEEN
PROJECTS
CONS
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
SPA
REALITY
SHARED
NODE.JS
CODE
SHARED
PHP
CODE
3 DEVS 2 DEVS 1 DEV
REACT
PHPNODE.JS
GATEWAYREPORTINGSEARCH SECURITYPAYMENT
▸ LOWER NUMBER OF TECHS = EASIER
MAINTANANCE
▸ SHARED CODE BETWEEN SAME TECH PROJECTS
▸ SHARED BUILD/DEPLOY PROCESS BETWEEN SAME
TECH
▸ SHARED STRUCTURE BETWEEN SAME TECH
PROJECTS
▸ YOU CAN MOVE FREELY BETWEEN PROJECTS OF
SAME TECH
PROS
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
▸ LOWER PERFORMANCE = WE CANNOT USE THE
BEST POSSIBLE TOOLS
▸ HARDER TO KEEP IT UP TO DATE
CONS
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
GATEWAY
REPORTING
SEARCH
SECURITY
PAYMENT
SPA
TSH REALITY = MONOREPO
3 DEVS 2 DEVS 1 DEVS
REACTPHPNODE.JS
▸ EASIEST TO DEVELOP
▸ STILL MODULAR
PROS
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
▸ LARGER CODE BASE
▸ HARDER TO KEEP BOUNDARIES
CONS
THE MOST BORING PART
OF A NEW SERVICE?
PLANNING?
ARCHITECTURE?
SERVICE
BOILERPLATE!
security
src
app
grpc
proto
service
container.ts
index.ts
SERVICE SETUP
SAME STRUCTURE
FOR EVERY
SERVICE
+
CUSTOM
MADE
OR
SERVICE
GENERATOR
= SECURITY
SERVICE
SETTING UP SERVICE AT TSH
tools create-service —project-name security
/services
/security
/src
/app
/grpc
/proto
/service
container.ts
index.ts
FOCUS ON BUSINESS LOGIC
NOT SERVICE STRUCTURE
WHAT’S NEXT?
SERVICE NEEDS
A CONTRACT
POSSIBLE SOLUTIONS
OUR CHOICE
WHY DO WE NEED IT?
TO GENERATE THINGS!
▸ CLIENTS
▸ TYPES
▸ DTO’S
▸ COMMANDS / HANDLERS / ROUTES SKELETONS
THINGS GENERATED FROM CONTRACTS
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
GENERATING FROM PROTO AT TSH
syntax = "proto3";
import "messages/send-notification.proto";
import "messages/acknowledge-notification.proto";
import "messages/get-notifications.proto";
import "messages/get-notification.proto";
package notifications;
service NotificationsService {
rpc sendNotification (SendNotificationRequest) returns (SendNotificationResponse) {}
rpc acknowledgeNotification (AcknowledgeNotificationRequest) returns (AcknowledgeNotificationResponse) {}
rpc getNotifications (GetNotificationsRequest) returns (GetNotificationsResponse) {}
rpc getNotification (GetNotificationRequest) returns (GetNotificationResponse) {}
}
GENERATING FROM PROTO AT TSH
tools from-proto —service-name security --generator-type=client 
/services
/security
/src
/grpc
/client
index.ts
/types
index.ts
index.ts
/proto
/service
service.ts
tools from-proto —service-name security --generator-type=service 
GENERATING FROM PROTO AT TSH
/*****************************************/
/* THIS FILE WAS GENERATED */
/* DO NOT TOUCH */
/*****************************************/
import { Observable } from 'rxjs'
import * as grpc from 'grpc'
import { resolve } from 'path'
import { Logger, loadMessageDefinition, toPromise, toObservable } from 'brickvest-js-common'
import {
SendNotificationRequest,
SendNotificationResponse,
AcknowledgeNotificationRequest,
AcknowledgeNotificationResponse,
GetNotificationsRequest,
GetNotificationsResponse,
GetNotificationRequest,
GetNotificationResponse,
GetUnacknowledgedNotificationsCountRequest,
GetUnacknowledgedNotificationsCountResponse,
NotificationStreamToService,
NotificationStreamToClient,
} from '../types'
type ClientDependencies = {
uri: string
logger: Logger
}
class NotificationsClient {
private client: any
constructor(private dependencies: ClientDependencies) {
const messageDefinition = loadMessageDefinition(resolve(__dirname, '../../proto/notifications-service.proto'))
const proto: any = grpc.loadPackageDefinition(messageDefinition).notifications
this.client = new proto.NotificationsService(dependencies.uri, grpc.credentials.createInsecure())
}
public sendNotification(request: SendNotificationRequest): Promise<SendNotificationResponse> {
this.dependencies.logger.info(
`Notifications service client handling: sendNotification (${JSON.stringify(request)})`
)
return toPromise<SendNotificationRequest, SendNotificationResponse>(this.client, 'sendNotification')(request)
}
public acknowledgeNotification(request: AcknowledgeNotificationRequest): Promise<AcknowledgeNotificationResponse> {
this.dependencies.logger.info(
`Notifications service client handling: acknowledgeNotification (${JSON.stringify(request)})`
)
return toPromise<AcknowledgeNotificationRequest, AcknowledgeNotificationResponse>(
this.client,
'acknowledgeNotification'
)(request)
}
public getNotifications(request: GetNotificationsRequest): Promise<GetNotificationsResponse> {
this.dependencies.logger.info(
`Notifications service client handling: getNotifications (${JSON.stringify(request)})`
)
return toPromise<GetNotificationsRequest, GetNotificationsResponse>(this.client, 'getNotifications')(request)
}
public getNotification(request: GetNotificationRequest): Promise<GetNotificationResponse> {
this.dependencies.logger.info(`Notifications service client handling: getNotification (${JSON.stringify(request)})`)
return toPromise<GetNotificationRequest, GetNotificationResponse>(this.client, 'getNotification')(request)
}
public getUnacknowledgedNotificationsCount(
request: GetUnacknowledgedNotificationsCountRequest
): Promise<GetUnacknowledgedNotificationsCountResponse> {
this.dependencies.logger.info(
`Notifications service client handling: getUnacknowledgedNotificationsCount (${JSON.stringify(request)})`
)
return toPromise<GetUnacknowledgedNotificationsCountRequest, GetUnacknowledgedNotificationsCountResponse>(
this.client,
'getUnacknowledgedNotificationsCount'
)(request)
}
public notificationsStream(request: NotificationStreamToService): Promise<Observable<NotificationStreamToClient>> {
this.dependencies.logger.info(
`Notifications service client handling: notificationsStream (${JSON.stringify(request)})`
)
return toObservable<NotificationStreamToService, NotificationStreamToClient>(this.client, 'notificationsStream')(
request
)
}
}
export { NotificationsClient }
KEEP SAME CODE STYLE
AND USE STATIC ANALYSIS
TOOLS
LOCAL DEVELOPMENT
DOCKER
&
DOCKER-COMPOSE
DOCKERFILE
FROM node:10.13-alpine
ARG NPM_TOKEN
RUN echo “registry=https://private-repository.com/repository/npm/“ > /root/.npmrc;
RUN echo "always-auth=true" >> /root/.npmrc;
RUN echo "_auth=${NPM_TOKEN}" >> /root/.npmrc;
WORKDIR /dir
COPY . .
RUN npm config set unsafe-perm true
RUN apk add bash
RUN npm install ts-node ts-node-dev typescript -g
RUN npm i
EXPOSE 50050
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
SINGLE IMAGE
MULTIPLE ENTRYPOINTS
DOCKER-COMPOSE
messaging:
image: our-app:latest
container_name: messaging
command: [bash, -c, 'ts-node-dev --poll ./services/messaging/src/index.ts’]
hostname:messaging
volumes: *volumes
depends_on:
- data
gateway:
image: our-app:latest
container_name: gateway
command: [bash, -c, 'ts-node-dev --poll ./services/gateway/src/index.ts']
hostname: gateway
volumes: *volumes
depends_on:
- messaging
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
YAML ANCHORS AND REFERENCES TO KEEP IT CLEAN
js:
image: our-app:latest
build:
context: .
dockerfile: docker/dev/Dockerfile
args:
- NPM_TOKEN
volumes: &volumes
- ./:/dir
- /dir/build/
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
WHAT ABOUT TESTS?
TESTING TROPHY
TESTS AS DOCKER CONTAINER
integration-tests:
image: our-app:latest
command:
[
'bash',
'-c',
‘./docker/wait.sh ldap-service 636 ./docker/wait.sh security 50050 npm run integration-tests',
]
volumes: *volumes
depends_on:
- messaging
- security
- ui-gateway
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
INTEGRATION TESTS
ARE EASY
BUT BEWARE OF
ASYNC
WHAT’S WRONG ON THIS PICTURE?
test('Gateway - workflow - create user test', { timeout: 10000 }, async (t: test.Test) => {
const clientSocket = await connectors.getConnector(config.clients.socketIO.type, config.clients.socketIO)
const validateMessage = createSocketValidator(clientSocket)
const connect$ = fromEvent(clientSocket, 'connect')
const mailerClientConfig = config.clients.mailerClient
const emailCountBeforeSending = await getCurrentEmailsCount(mailerClientConfig.mailHogUri)
connect$.subscribe(async () => {
(…)
t.end();
});
});
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
WHAT’S WRONG ON THIS PICTURE?
test('Gateway - workflow - create user test', { timeout: 10000 }, async (t: test.Test) => {
const clientSocket = await connectors.getConnector(config.clients.socketIO.type, config.clients.socketIO)
const validateMessage = createSocketValidator(clientSocket)
const connect$ = fromEvent(clientSocket, 'connect')
const mailerClientConfig = config.clients.mailerClient
const emailCountBeforeSending = await getCurrentEmailsCount(mailerClientConfig.mailHogUri)
connect$.subscribe(async () => {
(…)
t.end();
});
});
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
WHAT ?!
SOLUTION
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
test('Gateway - workflow - create user test', { timeout: 10000 }, async (t: test.Test) => {
const mailerClientConfig = config.clients.mailerClient
const emailCountBeforeSending = await getCurrentEmailsCount(mailerClientConfig.mailHogUri)
const clientSocket = await connectors.getConnector(config.clients.socketIO.type, config.clients.socketIO)
const validateMessage = createSocketValidator(clientSocket)
const connect$ = fromEvent(clientSocket, 'connect')
connect$.subscribe(async () => {
(…)
t.end();
});
});
WHAT ABOUT
NEGATIVE PATHS?
YOU CAN CONTROL
SERVICES DIRECTLY
FROM TESTS
PASS DOCKER SOCKET TO CONTAINER
js:
image: our-app:latest
build:
context: .
dockerfile: docker/dev/Dockerfile
args:
- NPM_TOKEN
volumes: &volumes
- ./:/dir
- /dir/build/
- /var/run/docker.sock:/var/run/docker.sock
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
CONTROL CONTAINERS FROM TESTS CONTAINER
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
test('Security integration tests - should reconnect to security service', async (t: test.Test) => {
pause(config.containers.security.name)
const payload = {…}
const authenticate = apiGatewayClient.proxy({
payload,
method: 'authenticate',
service: 'security'
})
const timedOut = await Promise.race([waitForTimeout, authenticate])
timedOut === true ? t.pass() : t.fail()
await ensureAreUpAndUnpaused([config.containers.security])
t.end()
})
CONTROL CONTAINERS FROM TESTS CONTAINER
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
test('Security integration tests - should reconnect to security service', async (t: test.Test) => {
pause(config.containers.security.name)
const payload = {…}
const authenticate = apiGatewayClient.proxy({
payload,
method: 'authenticate',
service: 'security'
})
const timedOut = await Promise.race([waitForTimeout, authenticate])
timedOut === true ? t.pass() : t.fail()
await ensureAreUpAndUnpaused([config.containers.security])
t.end()
})
CONTROL CONTAINERS FROM TESTS CONTAINER
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
export const ensureAreUpAndUnpaused = (containers: ContainerConfig[]): Promise<any> => {
const upOrUnpause: Array<Promise<any>> = []
containers.forEach(container => {
if (isPaused(container.name)) {
upOrUnpause.push(unpause(container))
} else if (isDown(container.name)) {
upOrUnpause.push(up(container))
}
})
return Promise.all(upOrUnpause)
}
export const pause = (containerName: string) => shell.exec(`docker pause ${containerName}`)
▸ MONOREPO IS EASIER TO DEVELOP WITH
▸ AUTOMATE PROJECT CREATION
▸ USE CONTRACTS AND GENERATE CODE FROM
THEM
▸ USE DOCKER
▸ FOCUS ON INTEGRATION TESTS
▸ TEST NEGATIVE PATHS
TL/DR
(MICRO?) SERVICES ARCHITECTURE IN PRACTICE
QUESTIONS ?
THANK YOU

More Related Content

Similar to (Micro?)services architecture in practice

Full stack development best practice and toolset
Full stack development best practice and toolsetFull stack development best practice and toolset
Full stack development best practice and toolsetReid Lai
 
Why Kubernetes? Cloud Native and Developer Experience at Zalando - OWL Tech &...
Why Kubernetes? Cloud Native and Developer Experience at Zalando - OWL Tech &...Why Kubernetes? Cloud Native and Developer Experience at Zalando - OWL Tech &...
Why Kubernetes? Cloud Native and Developer Experience at Zalando - OWL Tech &...Henning Jacobs
 
Android 103 - Firebase and Architecture Components
Android 103 - Firebase and Architecture ComponentsAndroid 103 - Firebase and Architecture Components
Android 103 - Firebase and Architecture ComponentsKai Koenig
 
Enterprise State Management with NGRX/platform
Enterprise State Management with NGRX/platformEnterprise State Management with NGRX/platform
Enterprise State Management with NGRX/platformIlia Idakiev
 
AWS Sydney Summit 2013 - Continuous Deployment Practices, with Production, Te...
AWS Sydney Summit 2013 - Continuous Deployment Practices, with Production, Te...AWS Sydney Summit 2013 - Continuous Deployment Practices, with Production, Te...
AWS Sydney Summit 2013 - Continuous Deployment Practices, with Production, Te...Amazon Web Services
 
Application Modernisation with PKS
Application Modernisation with PKSApplication Modernisation with PKS
Application Modernisation with PKSPhil Reay
 
Application Modernisation with PKS
Application Modernisation with PKSApplication Modernisation with PKS
Application Modernisation with PKSPhil Reay
 
Developer Intro to OpenShift
Developer Intro to OpenShiftDeveloper Intro to OpenShift
Developer Intro to OpenShiftTiera Fann, MBA
 
Developer intro to open shift
Developer intro to open shiftDeveloper intro to open shift
Developer intro to open shiftRam Maddali
 
[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습
[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습
[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습Oracle Korea
 
CQRS and Event Sourcing
CQRS and Event Sourcing CQRS and Event Sourcing
CQRS and Event Sourcing Inho Kang
 
App Mod 02: A developer intro to open shift
App Mod 02: A developer intro to open shiftApp Mod 02: A developer intro to open shift
App Mod 02: A developer intro to open shiftJudy Breedlove
 
Velocity NY 2016 - Devops: Who Does What?
Velocity NY 2016 - Devops: Who Does What?Velocity NY 2016 - Devops: Who Does What?
Velocity NY 2016 - Devops: Who Does What?cornelia davis
 
Cloud-native .NET Microservices mit Kubernetes
Cloud-native .NET Microservices mit KubernetesCloud-native .NET Microservices mit Kubernetes
Cloud-native .NET Microservices mit KubernetesQAware GmbH
 
Openshift Container Platform: First ItalyMeetup
Openshift Container Platform: First ItalyMeetupOpenshift Container Platform: First ItalyMeetup
Openshift Container Platform: First ItalyMeetupGiuseppe Bonocore
 
Advanced Topics - Session 1 - Continuous Deployment Practices on AWS
Advanced Topics - Session 1 - Continuous Deployment Practices on AWSAdvanced Topics - Session 1 - Continuous Deployment Practices on AWS
Advanced Topics - Session 1 - Continuous Deployment Practices on AWSAmazon Web Services
 
IBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js MicroservicesIBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js MicroservicesChris Bailey
 
Improving velocity through abstraction
Improving velocity through abstractionImproving velocity through abstraction
Improving velocity through abstractionVictorSzoltysek
 
Faster, more Secure Application Modernization and Replatforming with PKS - Ku...
Faster, more Secure Application Modernization and Replatforming with PKS - Ku...Faster, more Secure Application Modernization and Replatforming with PKS - Ku...
Faster, more Secure Application Modernization and Replatforming with PKS - Ku...VMware Tanzu
 
CI/CD and TDD in deploying kamailio
CI/CD and TDD in deploying kamailioCI/CD and TDD in deploying kamailio
CI/CD and TDD in deploying kamailioAleksandar Sosic
 

Similar to (Micro?)services architecture in practice (20)

Full stack development best practice and toolset
Full stack development best practice and toolsetFull stack development best practice and toolset
Full stack development best practice and toolset
 
Why Kubernetes? Cloud Native and Developer Experience at Zalando - OWL Tech &...
Why Kubernetes? Cloud Native and Developer Experience at Zalando - OWL Tech &...Why Kubernetes? Cloud Native and Developer Experience at Zalando - OWL Tech &...
Why Kubernetes? Cloud Native and Developer Experience at Zalando - OWL Tech &...
 
Android 103 - Firebase and Architecture Components
Android 103 - Firebase and Architecture ComponentsAndroid 103 - Firebase and Architecture Components
Android 103 - Firebase and Architecture Components
 
Enterprise State Management with NGRX/platform
Enterprise State Management with NGRX/platformEnterprise State Management with NGRX/platform
Enterprise State Management with NGRX/platform
 
AWS Sydney Summit 2013 - Continuous Deployment Practices, with Production, Te...
AWS Sydney Summit 2013 - Continuous Deployment Practices, with Production, Te...AWS Sydney Summit 2013 - Continuous Deployment Practices, with Production, Te...
AWS Sydney Summit 2013 - Continuous Deployment Practices, with Production, Te...
 
Application Modernisation with PKS
Application Modernisation with PKSApplication Modernisation with PKS
Application Modernisation with PKS
 
Application Modernisation with PKS
Application Modernisation with PKSApplication Modernisation with PKS
Application Modernisation with PKS
 
Developer Intro to OpenShift
Developer Intro to OpenShiftDeveloper Intro to OpenShift
Developer Intro to OpenShift
 
Developer intro to open shift
Developer intro to open shiftDeveloper intro to open shift
Developer intro to open shift
 
[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습
[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습
[Hands-on] CQRS(Command Query Responsibility Segregation) 와 Event Sourcing 패턴 실습
 
CQRS and Event Sourcing
CQRS and Event Sourcing CQRS and Event Sourcing
CQRS and Event Sourcing
 
App Mod 02: A developer intro to open shift
App Mod 02: A developer intro to open shiftApp Mod 02: A developer intro to open shift
App Mod 02: A developer intro to open shift
 
Velocity NY 2016 - Devops: Who Does What?
Velocity NY 2016 - Devops: Who Does What?Velocity NY 2016 - Devops: Who Does What?
Velocity NY 2016 - Devops: Who Does What?
 
Cloud-native .NET Microservices mit Kubernetes
Cloud-native .NET Microservices mit KubernetesCloud-native .NET Microservices mit Kubernetes
Cloud-native .NET Microservices mit Kubernetes
 
Openshift Container Platform: First ItalyMeetup
Openshift Container Platform: First ItalyMeetupOpenshift Container Platform: First ItalyMeetup
Openshift Container Platform: First ItalyMeetup
 
Advanced Topics - Session 1 - Continuous Deployment Practices on AWS
Advanced Topics - Session 1 - Continuous Deployment Practices on AWSAdvanced Topics - Session 1 - Continuous Deployment Practices on AWS
Advanced Topics - Session 1 - Continuous Deployment Practices on AWS
 
IBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js MicroservicesIBM Cloud University: Build, Deploy and Scale Node.js Microservices
IBM Cloud University: Build, Deploy and Scale Node.js Microservices
 
Improving velocity through abstraction
Improving velocity through abstractionImproving velocity through abstraction
Improving velocity through abstraction
 
Faster, more Secure Application Modernization and Replatforming with PKS - Ku...
Faster, more Secure Application Modernization and Replatforming with PKS - Ku...Faster, more Secure Application Modernization and Replatforming with PKS - Ku...
Faster, more Secure Application Modernization and Replatforming with PKS - Ku...
 
CI/CD and TDD in deploying kamailio
CI/CD and TDD in deploying kamailioCI/CD and TDD in deploying kamailio
CI/CD and TDD in deploying kamailio
 

More from The Software House

Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...The Software House
 
Jak efektywnie podejść do certyfikacji w AWS?
Jak efektywnie podejść do certyfikacji w AWS?Jak efektywnie podejść do certyfikacji w AWS?
Jak efektywnie podejść do certyfikacji w AWS?The Software House
 
O co chodzi z tą dostępnością cyfrową?
O co chodzi z tą dostępnością cyfrową?O co chodzi z tą dostępnością cyfrową?
O co chodzi z tą dostępnością cyfrową?The Software House
 
Chat tekstowy z użyciem Amazon Chime
Chat tekstowy z użyciem Amazon ChimeChat tekstowy z użyciem Amazon Chime
Chat tekstowy z użyciem Amazon ChimeThe Software House
 
Jak nie zwariować z architekturą Serverless?
Jak nie zwariować z architekturą Serverless?Jak nie zwariować z architekturą Serverless?
Jak nie zwariować z architekturą Serverless?The Software House
 
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWSAnaliza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWSThe Software House
 
Feature flags na ratunek projektu w JavaScript
Feature flags na ratunek projektu w JavaScriptFeature flags na ratunek projektu w JavaScript
Feature flags na ratunek projektu w JavaScriptThe Software House
 
Typowanie nominalne w TypeScript
Typowanie nominalne w TypeScriptTypowanie nominalne w TypeScript
Typowanie nominalne w TypeScriptThe Software House
 
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQL
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQLAutomatyzacja tworzenia frontendu z wykorzystaniem GraphQL
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQLThe Software House
 
Serverless Compose vs hurtownia danych
Serverless Compose vs hurtownia danychServerless Compose vs hurtownia danych
Serverless Compose vs hurtownia danychThe Software House
 
Testy API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięciTesty API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięciThe Software House
 
Jak skutecznie read model. Case study
Jak skutecznie read model. Case studyJak skutecznie read model. Case study
Jak skutecznie read model. Case studyThe Software House
 
Firestore czyli ognista baza od giganta z Doliny Krzemowej
Firestore czyli ognista baza od giganta z Doliny KrzemowejFirestore czyli ognista baza od giganta z Doliny Krzemowej
Firestore czyli ognista baza od giganta z Doliny KrzemowejThe Software House
 
Jak utrzymać stado Lambd w ryzach
Jak utrzymać stado Lambd w ryzachJak utrzymać stado Lambd w ryzach
Jak utrzymać stado Lambd w ryzachThe Software House
 
O łączeniu Storyblok i Next.js
O łączeniu Storyblok i Next.jsO łączeniu Storyblok i Next.js
O łączeniu Storyblok i Next.jsThe Software House
 
Amazon Step Functions. Sposób na implementację procesów w chmurze
Amazon Step Functions. Sposób na implementację procesów w chmurzeAmazon Step Functions. Sposób na implementację procesów w chmurze
Amazon Step Functions. Sposób na implementację procesów w chmurzeThe Software House
 
Od Figmy do gotowej aplikacji bez linijki kodu
Od Figmy do gotowej aplikacji bez linijki koduOd Figmy do gotowej aplikacji bez linijki kodu
Od Figmy do gotowej aplikacji bez linijki koduThe Software House
 

More from The Software House (20)

Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
 
Uszanowanko Podsumowanko
Uszanowanko PodsumowankoUszanowanko Podsumowanko
Uszanowanko Podsumowanko
 
Jak efektywnie podejść do certyfikacji w AWS?
Jak efektywnie podejść do certyfikacji w AWS?Jak efektywnie podejść do certyfikacji w AWS?
Jak efektywnie podejść do certyfikacji w AWS?
 
O co chodzi z tą dostępnością cyfrową?
O co chodzi z tą dostępnością cyfrową?O co chodzi z tą dostępnością cyfrową?
O co chodzi z tą dostępnością cyfrową?
 
Chat tekstowy z użyciem Amazon Chime
Chat tekstowy z użyciem Amazon ChimeChat tekstowy z użyciem Amazon Chime
Chat tekstowy z użyciem Amazon Chime
 
Migracje danych serverless
Migracje danych serverlessMigracje danych serverless
Migracje danych serverless
 
Jak nie zwariować z architekturą Serverless?
Jak nie zwariować z architekturą Serverless?Jak nie zwariować z architekturą Serverless?
Jak nie zwariować z architekturą Serverless?
 
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWSAnaliza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
 
Feature flags na ratunek projektu w JavaScript
Feature flags na ratunek projektu w JavaScriptFeature flags na ratunek projektu w JavaScript
Feature flags na ratunek projektu w JavaScript
 
Typowanie nominalne w TypeScript
Typowanie nominalne w TypeScriptTypowanie nominalne w TypeScript
Typowanie nominalne w TypeScript
 
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQL
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQLAutomatyzacja tworzenia frontendu z wykorzystaniem GraphQL
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQL
 
Serverless Compose vs hurtownia danych
Serverless Compose vs hurtownia danychServerless Compose vs hurtownia danych
Serverless Compose vs hurtownia danych
 
Testy API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięciTesty API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięci
 
Jak skutecznie read model. Case study
Jak skutecznie read model. Case studyJak skutecznie read model. Case study
Jak skutecznie read model. Case study
 
Firestore czyli ognista baza od giganta z Doliny Krzemowej
Firestore czyli ognista baza od giganta z Doliny KrzemowejFirestore czyli ognista baza od giganta z Doliny Krzemowej
Firestore czyli ognista baza od giganta z Doliny Krzemowej
 
Jak utrzymać stado Lambd w ryzach
Jak utrzymać stado Lambd w ryzachJak utrzymać stado Lambd w ryzach
Jak utrzymać stado Lambd w ryzach
 
Jak poskromić AWS?
Jak poskromić AWS?Jak poskromić AWS?
Jak poskromić AWS?
 
O łączeniu Storyblok i Next.js
O łączeniu Storyblok i Next.jsO łączeniu Storyblok i Next.js
O łączeniu Storyblok i Next.js
 
Amazon Step Functions. Sposób na implementację procesów w chmurze
Amazon Step Functions. Sposób na implementację procesów w chmurzeAmazon Step Functions. Sposób na implementację procesów w chmurze
Amazon Step Functions. Sposób na implementację procesów w chmurze
 
Od Figmy do gotowej aplikacji bez linijki kodu
Od Figmy do gotowej aplikacji bez linijki koduOd Figmy do gotowej aplikacji bez linijki kodu
Od Figmy do gotowej aplikacji bez linijki kodu
 

Recently uploaded

Russian Call Girls in Kolkata Samaira 🤌 8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Samaira 🤌  8250192130 🚀 Vip Call Girls KolkataRussian Call Girls in Kolkata Samaira 🤌  8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Samaira 🤌 8250192130 🚀 Vip Call Girls Kolkataanamikaraghav4
 
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)Dana Luther
 
Git and Github workshop GDSC MLRITM
Git and Github  workshop GDSC MLRITMGit and Github  workshop GDSC MLRITM
Git and Github workshop GDSC MLRITMgdsc13
 
定制(Management毕业证书)新加坡管理大学毕业证成绩单原版一比一
定制(Management毕业证书)新加坡管理大学毕业证成绩单原版一比一定制(Management毕业证书)新加坡管理大学毕业证成绩单原版一比一
定制(Management毕业证书)新加坡管理大学毕业证成绩单原版一比一Fs
 
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls KolkataVIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkataanamikaraghav4
 
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130  Available With RoomVIP Kolkata Call Girl Alambazar 👉 8250192130  Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Roomdivyansh0kumar0
 
Russian Call girls in Dubai +971563133746 Dubai Call girls
Russian  Call girls in Dubai +971563133746 Dubai  Call girlsRussian  Call girls in Dubai +971563133746 Dubai  Call girls
Russian Call girls in Dubai +971563133746 Dubai Call girlsstephieert
 
Call Girls In Mumbai Central Mumbai ❤️ 9920874524 👈 Cash on Delivery
Call Girls In Mumbai Central Mumbai ❤️ 9920874524 👈 Cash on DeliveryCall Girls In Mumbai Central Mumbai ❤️ 9920874524 👈 Cash on Delivery
Call Girls In Mumbai Central Mumbai ❤️ 9920874524 👈 Cash on Deliverybabeytanya
 
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一Fs
 
VIP 7001035870 Find & Meet Hyderabad Call Girls Dilsukhnagar high-profile Cal...
VIP 7001035870 Find & Meet Hyderabad Call Girls Dilsukhnagar high-profile Cal...VIP 7001035870 Find & Meet Hyderabad Call Girls Dilsukhnagar high-profile Cal...
VIP 7001035870 Find & Meet Hyderabad Call Girls Dilsukhnagar high-profile Cal...aditipandeya
 
VIP Kolkata Call Girl Dum Dum 👉 8250192130 Available With Room
VIP Kolkata Call Girl Dum Dum 👉 8250192130  Available With RoomVIP Kolkata Call Girl Dum Dum 👉 8250192130  Available With Room
VIP Kolkata Call Girl Dum Dum 👉 8250192130 Available With Roomdivyansh0kumar0
 
Russian Call Girls in Kolkata Ishita 🤌 8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Ishita 🤌  8250192130 🚀 Vip Call Girls KolkataRussian Call Girls in Kolkata Ishita 🤌  8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Ishita 🤌 8250192130 🚀 Vip Call Girls Kolkataanamikaraghav4
 
Sushant Golf City / best call girls in Lucknow | Service-oriented sexy call g...
Sushant Golf City / best call girls in Lucknow | Service-oriented sexy call g...Sushant Golf City / best call girls in Lucknow | Service-oriented sexy call g...
Sushant Golf City / best call girls in Lucknow | Service-oriented sexy call g...akbard9823
 
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一Fs
 
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012Call Girls South Delhi Delhi reach out to us at ☎ 9711199012
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012rehmti665
 
定制(CC毕业证书)美国美国社区大学毕业证成绩单原版一比一
定制(CC毕业证书)美国美国社区大学毕业证成绩单原版一比一定制(CC毕业证书)美国美国社区大学毕业证成绩单原版一比一
定制(CC毕业证书)美国美国社区大学毕业证成绩单原版一比一3sw2qly1
 
Complet Documnetation for Smart Assistant Application for Disabled Person
Complet Documnetation   for Smart Assistant Application for Disabled PersonComplet Documnetation   for Smart Assistant Application for Disabled Person
Complet Documnetation for Smart Assistant Application for Disabled Personfurqan222004
 

Recently uploaded (20)

Russian Call Girls in Kolkata Samaira 🤌 8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Samaira 🤌  8250192130 🚀 Vip Call Girls KolkataRussian Call Girls in Kolkata Samaira 🤌  8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Samaira 🤌 8250192130 🚀 Vip Call Girls Kolkata
 
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
Packaging the Monolith - PHP Tek 2024 (Breaking it down one bite at a time)
 
Model Call Girl in Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in  Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝Model Call Girl in  Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Jamuna Vihar Delhi reach out to us at 🔝9953056974🔝
 
Git and Github workshop GDSC MLRITM
Git and Github  workshop GDSC MLRITMGit and Github  workshop GDSC MLRITM
Git and Github workshop GDSC MLRITM
 
定制(Management毕业证书)新加坡管理大学毕业证成绩单原版一比一
定制(Management毕业证书)新加坡管理大学毕业证成绩单原版一比一定制(Management毕业证书)新加坡管理大学毕业证成绩单原版一比一
定制(Management毕业证书)新加坡管理大学毕业证成绩单原版一比一
 
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls KolkataVIP Call Girls Kolkata Ananya 🤌  8250192130 🚀 Vip Call Girls Kolkata
VIP Call Girls Kolkata Ananya 🤌 8250192130 🚀 Vip Call Girls Kolkata
 
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130  Available With RoomVIP Kolkata Call Girl Alambazar 👉 8250192130  Available With Room
VIP Kolkata Call Girl Alambazar 👉 8250192130 Available With Room
 
Call Girls In South Ex 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SERVICE
Call Girls In South Ex 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SERVICECall Girls In South Ex 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SERVICE
Call Girls In South Ex 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SERVICE
 
Russian Call girls in Dubai +971563133746 Dubai Call girls
Russian  Call girls in Dubai +971563133746 Dubai  Call girlsRussian  Call girls in Dubai +971563133746 Dubai  Call girls
Russian Call girls in Dubai +971563133746 Dubai Call girls
 
Call Girls In Mumbai Central Mumbai ❤️ 9920874524 👈 Cash on Delivery
Call Girls In Mumbai Central Mumbai ❤️ 9920874524 👈 Cash on DeliveryCall Girls In Mumbai Central Mumbai ❤️ 9920874524 👈 Cash on Delivery
Call Girls In Mumbai Central Mumbai ❤️ 9920874524 👈 Cash on Delivery
 
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一
定制(AUT毕业证书)新西兰奥克兰理工大学毕业证成绩单原版一比一
 
VIP 7001035870 Find & Meet Hyderabad Call Girls Dilsukhnagar high-profile Cal...
VIP 7001035870 Find & Meet Hyderabad Call Girls Dilsukhnagar high-profile Cal...VIP 7001035870 Find & Meet Hyderabad Call Girls Dilsukhnagar high-profile Cal...
VIP 7001035870 Find & Meet Hyderabad Call Girls Dilsukhnagar high-profile Cal...
 
sasti delhi Call Girls in munirka 🔝 9953056974 🔝 escort Service-
sasti delhi Call Girls in munirka 🔝 9953056974 🔝 escort Service-sasti delhi Call Girls in munirka 🔝 9953056974 🔝 escort Service-
sasti delhi Call Girls in munirka 🔝 9953056974 🔝 escort Service-
 
VIP Kolkata Call Girl Dum Dum 👉 8250192130 Available With Room
VIP Kolkata Call Girl Dum Dum 👉 8250192130  Available With RoomVIP Kolkata Call Girl Dum Dum 👉 8250192130  Available With Room
VIP Kolkata Call Girl Dum Dum 👉 8250192130 Available With Room
 
Russian Call Girls in Kolkata Ishita 🤌 8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Ishita 🤌  8250192130 🚀 Vip Call Girls KolkataRussian Call Girls in Kolkata Ishita 🤌  8250192130 🚀 Vip Call Girls Kolkata
Russian Call Girls in Kolkata Ishita 🤌 8250192130 🚀 Vip Call Girls Kolkata
 
Sushant Golf City / best call girls in Lucknow | Service-oriented sexy call g...
Sushant Golf City / best call girls in Lucknow | Service-oriented sexy call g...Sushant Golf City / best call girls in Lucknow | Service-oriented sexy call g...
Sushant Golf City / best call girls in Lucknow | Service-oriented sexy call g...
 
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一
定制(Lincoln毕业证书)新西兰林肯大学毕业证成绩单原版一比一
 
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012Call Girls South Delhi Delhi reach out to us at ☎ 9711199012
Call Girls South Delhi Delhi reach out to us at ☎ 9711199012
 
定制(CC毕业证书)美国美国社区大学毕业证成绩单原版一比一
定制(CC毕业证书)美国美国社区大学毕业证成绩单原版一比一定制(CC毕业证书)美国美国社区大学毕业证成绩单原版一比一
定制(CC毕业证书)美国美国社区大学毕业证成绩单原版一比一
 
Complet Documnetation for Smart Assistant Application for Disabled Person
Complet Documnetation   for Smart Assistant Application for Disabled PersonComplet Documnetation   for Smart Assistant Application for Disabled Person
Complet Documnetation for Smart Assistant Application for Disabled Person
 

(Micro?)services architecture in practice

  • 2. ADAM POLAK HEAD OF NODE.JS ADAM.POLAK@TSH.IO POLAK.ADAM1
  • 4. ▸ SPECIALIZED SMALL APPS ▸ SEPARATE REPOS ▸ OWN STRUCTURE, API AND LANGUAGE ▸ INDEPENDENT BUILDS, TESTS AND DEPLOYS ▸ EASY TO MAINTAIN BECAUSE OF SMALL CODE BASE THEORY (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 6. ▸ 5 SERVICES AT START ▸ SPA ▸ 6-7 DEVELOPERS AT START PROJECT (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 7. ▸ WHAT ABOUT REPOSITORIES? ▸ WHAT ABOUT API? ▸ WHAT ABOUT SETTING UP NEW SERVICE? ▸ WHAT ABOUT DEVELOPMENT? ▸ WHAT ABOUT TESTS? ▸ AND MANY MANY MORE QUESTIONS? (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 10. USE CASE SUMARY (MICRO?) SERVICES ARCHITECTURE IN PRACTICE ▸ 2 “SERVICES” - SPA + API ▸ SEPARATE TEAMS ▸ DIFFERENT PROJECT STRUCTURE ▸ TECH PER PROJECT ▸ PRACTICES PER PROJECT
  • 12. GATEWAY PAYMENT USE CASE #2 - BACKEND REPORTINGSECURITYSEARCH
  • 13. USE CASE #2 - FRONTEND SPA GATEWAY
  • 15. GATEWAY NODE.JS 1 DEV SECURITY PHP 1 DEV REPORTING PHP 1 DEV PAYMENT .NET 1 DEV SEARCH PYTHON 1 DEV SPA REACT 1 DEV THEORY
  • 16. ▸ BEST AVAILABLE TECH FOR GIVEN TASK ▸ ??? PROS (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 17. ▸ 6 DIFFERENT TECH STACKS ▸ NO SHARED CODE = DUPLICATION ▸ 6 DIFFERENT BUILD/DEPLOY PROCESSES ▸ MUCH HARDER TO MOVE DEVS BETWEEN PROJECTS CONS (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 18. SPA REALITY SHARED NODE.JS CODE SHARED PHP CODE 3 DEVS 2 DEVS 1 DEV REACT PHPNODE.JS GATEWAYREPORTINGSEARCH SECURITYPAYMENT
  • 19. ▸ LOWER NUMBER OF TECHS = EASIER MAINTANANCE ▸ SHARED CODE BETWEEN SAME TECH PROJECTS ▸ SHARED BUILD/DEPLOY PROCESS BETWEEN SAME TECH ▸ SHARED STRUCTURE BETWEEN SAME TECH PROJECTS ▸ YOU CAN MOVE FREELY BETWEEN PROJECTS OF SAME TECH PROS (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 20. ▸ LOWER PERFORMANCE = WE CANNOT USE THE BEST POSSIBLE TOOLS ▸ HARDER TO KEEP IT UP TO DATE CONS (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 21. GATEWAY REPORTING SEARCH SECURITY PAYMENT SPA TSH REALITY = MONOREPO 3 DEVS 2 DEVS 1 DEVS REACTPHPNODE.JS
  • 22. ▸ EASIEST TO DEVELOP ▸ STILL MODULAR PROS (MICRO?) SERVICES ARCHITECTURE IN PRACTICE ▸ LARGER CODE BASE ▸ HARDER TO KEEP BOUNDARIES CONS
  • 23. THE MOST BORING PART OF A NEW SERVICE?
  • 27. security src app grpc proto service container.ts index.ts SERVICE SETUP SAME STRUCTURE FOR EVERY SERVICE + CUSTOM MADE OR SERVICE GENERATOR = SECURITY SERVICE
  • 28. SETTING UP SERVICE AT TSH tools create-service —project-name security /services /security /src /app /grpc /proto /service container.ts index.ts
  • 29. FOCUS ON BUSINESS LOGIC NOT SERVICE STRUCTURE
  • 33. WHY DO WE NEED IT?
  • 35. ▸ CLIENTS ▸ TYPES ▸ DTO’S ▸ COMMANDS / HANDLERS / ROUTES SKELETONS THINGS GENERATED FROM CONTRACTS (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 36. GENERATING FROM PROTO AT TSH syntax = "proto3"; import "messages/send-notification.proto"; import "messages/acknowledge-notification.proto"; import "messages/get-notifications.proto"; import "messages/get-notification.proto"; package notifications; service NotificationsService { rpc sendNotification (SendNotificationRequest) returns (SendNotificationResponse) {} rpc acknowledgeNotification (AcknowledgeNotificationRequest) returns (AcknowledgeNotificationResponse) {} rpc getNotifications (GetNotificationsRequest) returns (GetNotificationsResponse) {} rpc getNotification (GetNotificationRequest) returns (GetNotificationResponse) {} }
  • 37. GENERATING FROM PROTO AT TSH tools from-proto —service-name security --generator-type=client  /services /security /src /grpc /client index.ts /types index.ts index.ts /proto /service service.ts tools from-proto —service-name security --generator-type=service 
  • 38. GENERATING FROM PROTO AT TSH /*****************************************/ /* THIS FILE WAS GENERATED */ /* DO NOT TOUCH */ /*****************************************/ import { Observable } from 'rxjs' import * as grpc from 'grpc' import { resolve } from 'path' import { Logger, loadMessageDefinition, toPromise, toObservable } from 'brickvest-js-common' import { SendNotificationRequest, SendNotificationResponse, AcknowledgeNotificationRequest, AcknowledgeNotificationResponse, GetNotificationsRequest, GetNotificationsResponse, GetNotificationRequest, GetNotificationResponse, GetUnacknowledgedNotificationsCountRequest, GetUnacknowledgedNotificationsCountResponse, NotificationStreamToService, NotificationStreamToClient, } from '../types' type ClientDependencies = { uri: string logger: Logger } class NotificationsClient { private client: any constructor(private dependencies: ClientDependencies) { const messageDefinition = loadMessageDefinition(resolve(__dirname, '../../proto/notifications-service.proto')) const proto: any = grpc.loadPackageDefinition(messageDefinition).notifications this.client = new proto.NotificationsService(dependencies.uri, grpc.credentials.createInsecure()) } public sendNotification(request: SendNotificationRequest): Promise<SendNotificationResponse> { this.dependencies.logger.info( `Notifications service client handling: sendNotification (${JSON.stringify(request)})` ) return toPromise<SendNotificationRequest, SendNotificationResponse>(this.client, 'sendNotification')(request) } public acknowledgeNotification(request: AcknowledgeNotificationRequest): Promise<AcknowledgeNotificationResponse> { this.dependencies.logger.info( `Notifications service client handling: acknowledgeNotification (${JSON.stringify(request)})` ) return toPromise<AcknowledgeNotificationRequest, AcknowledgeNotificationResponse>( this.client, 'acknowledgeNotification' )(request) } public getNotifications(request: GetNotificationsRequest): Promise<GetNotificationsResponse> { this.dependencies.logger.info( `Notifications service client handling: getNotifications (${JSON.stringify(request)})` ) return toPromise<GetNotificationsRequest, GetNotificationsResponse>(this.client, 'getNotifications')(request) } public getNotification(request: GetNotificationRequest): Promise<GetNotificationResponse> { this.dependencies.logger.info(`Notifications service client handling: getNotification (${JSON.stringify(request)})`) return toPromise<GetNotificationRequest, GetNotificationResponse>(this.client, 'getNotification')(request) } public getUnacknowledgedNotificationsCount( request: GetUnacknowledgedNotificationsCountRequest ): Promise<GetUnacknowledgedNotificationsCountResponse> { this.dependencies.logger.info( `Notifications service client handling: getUnacknowledgedNotificationsCount (${JSON.stringify(request)})` ) return toPromise<GetUnacknowledgedNotificationsCountRequest, GetUnacknowledgedNotificationsCountResponse>( this.client, 'getUnacknowledgedNotificationsCount' )(request) } public notificationsStream(request: NotificationStreamToService): Promise<Observable<NotificationStreamToClient>> { this.dependencies.logger.info( `Notifications service client handling: notificationsStream (${JSON.stringify(request)})` ) return toObservable<NotificationStreamToService, NotificationStreamToClient>(this.client, 'notificationsStream')( request ) } } export { NotificationsClient }
  • 39. KEEP SAME CODE STYLE AND USE STATIC ANALYSIS TOOLS
  • 40.
  • 43. DOCKERFILE FROM node:10.13-alpine ARG NPM_TOKEN RUN echo “registry=https://private-repository.com/repository/npm/“ > /root/.npmrc; RUN echo "always-auth=true" >> /root/.npmrc; RUN echo "_auth=${NPM_TOKEN}" >> /root/.npmrc; WORKDIR /dir COPY . . RUN npm config set unsafe-perm true RUN apk add bash RUN npm install ts-node ts-node-dev typescript -g RUN npm i EXPOSE 50050 (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 46. DOCKER-COMPOSE messaging: image: our-app:latest container_name: messaging command: [bash, -c, 'ts-node-dev --poll ./services/messaging/src/index.ts’] hostname:messaging volumes: *volumes depends_on: - data gateway: image: our-app:latest container_name: gateway command: [bash, -c, 'ts-node-dev --poll ./services/gateway/src/index.ts'] hostname: gateway volumes: *volumes depends_on: - messaging (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 47. YAML ANCHORS AND REFERENCES TO KEEP IT CLEAN js: image: our-app:latest build: context: . dockerfile: docker/dev/Dockerfile args: - NPM_TOKEN volumes: &volumes - ./:/dir - /dir/build/ (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 50. TESTS AS DOCKER CONTAINER integration-tests: image: our-app:latest command: [ 'bash', '-c', ‘./docker/wait.sh ldap-service 636 ./docker/wait.sh security 50050 npm run integration-tests', ] volumes: *volumes depends_on: - messaging - security - ui-gateway (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 53. WHAT’S WRONG ON THIS PICTURE? test('Gateway - workflow - create user test', { timeout: 10000 }, async (t: test.Test) => { const clientSocket = await connectors.getConnector(config.clients.socketIO.type, config.clients.socketIO) const validateMessage = createSocketValidator(clientSocket) const connect$ = fromEvent(clientSocket, 'connect') const mailerClientConfig = config.clients.mailerClient const emailCountBeforeSending = await getCurrentEmailsCount(mailerClientConfig.mailHogUri) connect$.subscribe(async () => { (…) t.end(); }); }); (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 54. WHAT’S WRONG ON THIS PICTURE? test('Gateway - workflow - create user test', { timeout: 10000 }, async (t: test.Test) => { const clientSocket = await connectors.getConnector(config.clients.socketIO.type, config.clients.socketIO) const validateMessage = createSocketValidator(clientSocket) const connect$ = fromEvent(clientSocket, 'connect') const mailerClientConfig = config.clients.mailerClient const emailCountBeforeSending = await getCurrentEmailsCount(mailerClientConfig.mailHogUri) connect$.subscribe(async () => { (…) t.end(); }); }); (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 56. SOLUTION (MICRO?) SERVICES ARCHITECTURE IN PRACTICE test('Gateway - workflow - create user test', { timeout: 10000 }, async (t: test.Test) => { const mailerClientConfig = config.clients.mailerClient const emailCountBeforeSending = await getCurrentEmailsCount(mailerClientConfig.mailHogUri) const clientSocket = await connectors.getConnector(config.clients.socketIO.type, config.clients.socketIO) const validateMessage = createSocketValidator(clientSocket) const connect$ = fromEvent(clientSocket, 'connect') connect$.subscribe(async () => { (…) t.end(); }); });
  • 58. YOU CAN CONTROL SERVICES DIRECTLY FROM TESTS
  • 59. PASS DOCKER SOCKET TO CONTAINER js: image: our-app:latest build: context: . dockerfile: docker/dev/Dockerfile args: - NPM_TOKEN volumes: &volumes - ./:/dir - /dir/build/ - /var/run/docker.sock:/var/run/docker.sock (MICRO?) SERVICES ARCHITECTURE IN PRACTICE
  • 60. CONTROL CONTAINERS FROM TESTS CONTAINER (MICRO?) SERVICES ARCHITECTURE IN PRACTICE test('Security integration tests - should reconnect to security service', async (t: test.Test) => { pause(config.containers.security.name) const payload = {…} const authenticate = apiGatewayClient.proxy({ payload, method: 'authenticate', service: 'security' }) const timedOut = await Promise.race([waitForTimeout, authenticate]) timedOut === true ? t.pass() : t.fail() await ensureAreUpAndUnpaused([config.containers.security]) t.end() })
  • 61. CONTROL CONTAINERS FROM TESTS CONTAINER (MICRO?) SERVICES ARCHITECTURE IN PRACTICE test('Security integration tests - should reconnect to security service', async (t: test.Test) => { pause(config.containers.security.name) const payload = {…} const authenticate = apiGatewayClient.proxy({ payload, method: 'authenticate', service: 'security' }) const timedOut = await Promise.race([waitForTimeout, authenticate]) timedOut === true ? t.pass() : t.fail() await ensureAreUpAndUnpaused([config.containers.security]) t.end() })
  • 62. CONTROL CONTAINERS FROM TESTS CONTAINER (MICRO?) SERVICES ARCHITECTURE IN PRACTICE export const ensureAreUpAndUnpaused = (containers: ContainerConfig[]): Promise<any> => { const upOrUnpause: Array<Promise<any>> = [] containers.forEach(container => { if (isPaused(container.name)) { upOrUnpause.push(unpause(container)) } else if (isDown(container.name)) { upOrUnpause.push(up(container)) } }) return Promise.all(upOrUnpause) } export const pause = (containerName: string) => shell.exec(`docker pause ${containerName}`)
  • 63. ▸ MONOREPO IS EASIER TO DEVELOP WITH ▸ AUTOMATE PROJECT CREATION ▸ USE CONTRACTS AND GENERATE CODE FROM THEM ▸ USE DOCKER ▸ FOCUS ON INTEGRATION TESTS ▸ TEST NEGATIVE PATHS TL/DR (MICRO?) SERVICES ARCHITECTURE IN PRACTICE