Soluzione multi-nodo per applicazioni web
Introduzione
Un servizio online se invocato da un numero molto alto di richieste sull'unità di tempo può "andare in sofferenza" e dare tempi di risposta troppo alti. In questo caso si può intervenire a livello sistemistico per ottimizzare le risorse coinvolte o aumentarle. Se ciò non dovesse bastare si possono accendere più istanze del servizio in modo che il carico di lavoro venga ripartito su queste e non su una singola istanza. Ogni istanza viene detta "nodo".
Architettura
Lo scenario con una singola istanza di una classica applicazione web composta da Gateway (GW - front-end), Servizio (SR - back-end) e Database (Db):
Lo scenario con un Servizio (SR) replicato in più nodi ma con il Database (DB) ed il Gateway (GW) in comune, quello che punto a costruire:
Implementazione
Per l'implementazione prevediamo che le componenti del sistema siano tutte dockerizzate e supponiamo che siano le seguenti:
- Gateway = Nginx
- Servizio = Pspdfkit
- Database = Postgres
Il docker-compose di questo stack sarebbe questo:
version: "3"services:db:image: postgres:latestenvironment:POSTGRES_USER: pspdfkitPOSTGRES_PASSWORD: password# ... other environment variablespspdfkit:image: "pspdfkit/pspdfkit:latest"environment:PGUSER: pspdfkitPGPASSWORD: password# ... other environment variablesdepends_on:- dbports:- "5000:5000"
Se provassimo a lanciarlo avremmo la porta 5000 che espone il servizio fornito da PdfDfKit.
Se questo servizio è utilizzato da tantissime applicazioni per unità di tempo e va in sofferenza potremmo usare l'opzione "--scale" di docker che consente di creare più istanze di un servizio "scalandolo". "Scale" prevede, a livello di sintassi il nome del servizio che si intende scalare e il numero di istanze che si intende ottenere:
$ docker-compose up --scale pspdfkit=3
Lanciando questo comando otterremmo lo start del primo nodo e poi un errore per conflitto di porta già occupata dagli altri due nodi che non partirebbero (trovando la 5000 occupata dal primo nodo).
La soluzione prevede una modifica al docker-compose con la quale dichiamo di esporre la porta 5000 interna su una porta a caso dell'host, con l'opzione "ports: - 5000":
version: "3"services:db:image: postgres:latestenvironment:POSTGRES_USER: pspdfkitPOSTGRES_PASSWORD: password# ... other environment variablespspdfkit:image: "pspdfkit/pspdfkit:latest"environment:PGUSER: pspdfkitPGPASSWORD: password# ... other environment variablesdepends_on:- dbports:- "5000"
Lanciando ora:
$ docker-compose up --scale pspdfkit=3
Si otterrà la partenza dei tre nodi. Per capire su quale porta stanno girando i servizi basterà chiederlo a docker:
$ docker ps
Capite bene che così il servizio è difficilmente utilizzabile e quindi chiediamo aiuto al proxy-pass costituito da Nginx. Basterà creare un file "nginx.conf" , nella stessa directory del docker-compose.yml, con il quale diciamo a Nginx di dirottare tutte le richieste che arrivano alla porta 4000 verso il servizio pspdfkit sulla porta 5000:
user nginx;events {worker_connections 1000;}http {server {listen 4000;location / {proxy_pass http://pspdfkit:5000;}}}
e poi chiederemo a docker di esporre la porta 4000:
version: "3"services:db:image: postgres:latestenvironment:POSTGRES_USER: pspdfkitPOSTGRES_PASSWORD: password# ... other environment variablespspdfkit:image: "pspdfkit/pspdfkit:latest"environment:PGUSER: pspdfkitPGPASSWORD: password# ... other environment variablesdepends_on:- dbexpose:- "5000"nginx:image: nginx:latestvolumes:- ./nginx.conf:/etc/nginx/nginx.conf:rodepends_on:- pspdfkitports:- "4000:4000"
Nginx gestirà le richieste che arriveranno sulla porta 4000 dirottandole alle istanze di pspdfkit disponibili con una logica "round robin" e quindi potremo lanciare:
$ docker-compose up --scale pspdfkit=3
Fonti:
Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale
Commenti
Posta un commento