Passa ai contenuti principali

Soluzione multi-nodo per applicazioni web

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:latest
environment:
POSTGRES_USER: pspdfkit
POSTGRES_PASSWORD: password
# ... other environment variables
pspdfkit:
image: "pspdfkit/pspdfkit:latest"

environment:
PGUSER: pspdfkit
PGPASSWORD: password
# ... other environment variables
depends_on:
- db
ports:
- "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:latest
environment:
POSTGRES_USER: pspdfkit
POSTGRES_PASSWORD: password
# ... other environment variables
pspdfkit:
image: "pspdfkit/pspdfkit:latest"

environment:
PGUSER: pspdfkit
PGPASSWORD: password
# ... other environment variables
depends_on:
- db
ports:
- "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:latest
environment:
POSTGRES_USER: pspdfkit
POSTGRES_PASSWORD: password
# ... other environment variables
pspdfkit:
image: "pspdfkit/pspdfkit:latest"

environment:
PGUSER: pspdfkit
PGPASSWORD: password
# ... other environment variables
depends_on:
- db
expose:
- "5000"
nginx:
image: nginx:latest
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- pspdfkit
ports:
- "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:






Commenti

Post popolari in questo blog

Telecamere Ip con accesso "nascosto"

Telecamere Ip con accesso "nascosto" Storia triste di un auto-hacking obbligato che mi ha fatto scoprire come la nostra privacy è realmente messa a rischi. Storia Ho acquistato dal mercatino/fiera del Radioamatore di Fasano quattro telecamere IP. La scatola riporta "Smart Camera" LF4810. Ne ho montata una e testata in tutte le sue funzionalità per oltre un mese. Chiaramente la manualistica scarsissima, come da tradizione in questi prodotti cinesi di costo molto concorrenziale, consiste in un "pieghevole" di 4 facciate. Chiaramente non erano documentate le impostazioni necessarie per attivare i protocolli ONVIF e RTSP che mi sono indispensabili per l'uso che ne devo fare. Nonostante questa scarsa documentazione dopo l'installazione base fatta con l'apposita app: tutto sembrava corretto. Chiaramente la prima azione che ho compiuto è stata quella di cambiare la password che di default è "123". Subito dopo h

Alzatapparella con Shelly 2 e Alexa

Alzatapparella con Shelly 2 e Alexa Qui spiego tutti i passaggi per installare lo Shelly 2 per automatizzare una tapparella e come configurarlo in Alexa. Impianto attuale Collegamenti da effettuare: Schema teorico: Collegamenti reali: Impostazioni: Dopo aver collegato tutto si procede alla configurazione. Prima di tutto installare la App "Shelly" cercandola nel proprio store e create un account: Il dispositivo verrà visto come doppio interruttore. Andare sulla "i" "Impostazioni": Nella sezione "MODO" ed impostare "Roller Shutter" Poi su "APRI/CHIUDI TEMPO DI LAVORO" ed impostare tipo 20 secondi. Altro passaggio importante in caso di tapparelle è quello relativo alla calibrazione (schermata relativa a "Shelly 2.5"). Se si omette questo passaggio non sarà possibile vedere in che stato è (aperta/chiusa

UPS Monitor via USB

Collegamenti Ho collegato l'UPS Mustek PowerMust 800 mediante il cavo USB al server con Ubuntu Linux 18.04. Software Ho installato: $ sudo apt-get install nut nut-cgi Configurazione Ho impostato i permessi di accesso: $ sudo chown root:nut /etc/nut/* $ sudo chown 640 /etc/nut/* Ho impostato nel file ups.conf (il file di configurazione del servizio) [mustek] driver = blazer_usb port = auto desc = "Musteck Power 800 usb" Ho impostato nel file upsd.conf (il file di configurazione del demone del servizio) LISTEN 127.0.0.1 3493 ACL all 0.0.0.0/0 ACL localhost 127.0.0.1/32 ACCEPT localhost REJECT all Ho impostato nel file upsd.users (il file di configurazione degli utenti del servizio) [mustek] password = 123456 allowfrom = localhost upsmon master Ho impostato nel file upsmon.conf (il file di configurazione del servizio di monitoraggio) MONITOR mustek@localhost 1 local_mon 123456 master Ho abilitato il servizio di moni