.. meta:: :language: it :description language=it: anatomia di client e server :description language=en: client and server anatomy :keywords: distributed system, client, server, anatomy :author: Luciano De Falco Alfano .. index:: anatomia di client e server .. _ref_anatomia_di_client_e_server: Anatomia di client e server ============================= .. contents:: :local: *Lezione del 2019-04-17 mer*. .. index:: client .. _ref_client: Client -------- I client hanno la funzione di permettere all'utente di interagire con i server. Questa funzionalità può avvenire in diversi modi. Il client può fornire accesso diretto ai servizi sul server dando all'utente la sola interfaccia. In questo contesto il server esegue tutto. Il client è detto **thin client**. Un esempio sono le macchine X windows, in cui i client non fanno altro che visualizzare la grafica decisa dal server. È possibile che il client ospiti componenti del software che vadano oltre la pura interfaccia grafica, facendosi carico di parte dell'applicazione. Per arrivare gradualmente fino ad estremi come le macchine ATM e i TV set-top boxes. In questi casi l'interfaccia utente può divenire una componente minoritaria del software presente nel cliente. Mentre possono essere preponderanti l'elaborazione locale e il supporto alle comunicazioni. Fin qui abbiamo parlato di requisiti funzionali del software. Ma vi possono essere anche requisiti non funzionali. Ad esempio la trasparenza per l'accesso ai dati di solito si implementa con un emulatore software su client che fornisce la stessa interfaccia del server, mascherando le differenze (formato dei dati e di comunicazione). La locazione, la migrazione e la rilocazione solitamente si ottengono tramite sistemi di nomi, con la cooperazione del software client. Ad esempio si consideri il funzionamento del cellulare. Quando si cammina, il cellulare misura la potenza del segnale della cella con cui sta lavorando, e la confronta con le potenze delle altre celle che riceve. Quando la potenza della cella di riferimento si abbassa in modo eccessivo, il cellulare (quindi il client) provvede a innescare il processo per cambiare cella di riferimento, chiedendo l'aggancio al segnale più potente tra quelli disponibili. Analogamente quando si è con i sistemi embedded. E il multiTCP. Questo significa che un client (cellulare) a livello 4 apre più canali TCP: ad es. tramite rete radio e tramite wifi. Ed instrada il traffico TCP sul canale più performante. Se il segnale del canale corrente si degrada, ad es. perché ci si allontana troppo dal punto d'accesso wifi, il cellulare passa il traffico TCP alla rete radio. Addirittura, se i segnali sono entrambi buoni, può fare load balancing su entrambe le reti [#]_. Questo è un esempio di rilocazione dei servizi. Anche il mascheramento degli errori di comunicazione, usualmente avviene lato client. .. index:: server .. _ref_server: Server -------- Un server è un processo che implementa uno specifico servizio utilizzato da una collezione di client. Vi sono più sistemi per organizzare i server. I server **iterativi** gestiscono direttamente le richieste e rispondono ai client. I server **concorrenti** non gestiscono direttamente la richiesta, ma la passano a un thread/processo separato, dopo di che si mettono in attesa della prossima richiesta. I server *concorrenti* vengono implementati con thread o con processi (ad es. in Unix tramite fork). *Lezione del 2019-04-18 gio*. La porta su cui il server lavora, o è catalogata, o è una porta conosciuta. Esistono superserver che lanciano altri server. Un superserver quando vede una chiamata sulla porta di competenza di un determinato server, lo attiva. Vi sono servizi Unix che fanno questo lavoro. E vale la pena utilizzare un superserver solo verso server che sono chiamati raramente. Può essere necessario avere due canali verso il server, uno di lavoro, e l'altro fuori banda per inviare le informazioni di controllo. Esempio classico è lo FTP. Un ulteriore aspetto da considerare è la eventuale necessità di gestire lo stato della richiesta. Un server con richieste senza stato è detto **stateless**, mentre se le richieste hanno uno stato da gestire, abbiamo server **stateful**. Un server *stateless* non ha necessità di memorizzare informazioni necessarie allo svolgimento del servizio richiesto del client. Si limita a rispondere inviando il dato richiesto. Se memorizza qualcosa relativo al passato, non è qualcosa necessario alla elaborazione del servizio richiesto. Il web server è un esempio di server *stateless*. In questo caso se è necessario mantere informazioni di stato, si è costretti a tenerle nel client (web o http cookie). Invece un server *stateful* ha necessità di mantenere informazioni per l'elaborazione del servizio richiesto, *per ogni client connesso*. Ad esempio, un file server ha necessità di mantenere lo stato delle richieste in corso da parte di ogni client, ad esempio per impedire scritture concorrenti sullo stesso file da parte di due diversi client. Gestire, o meno, lo stato della richiesta per ogni client ha un impatto molto rilevante. Lo sviluppo di server *stateless* è molto più semplice. Non solo perché ho meno dati da tenere sotto controllo, ma sopratutto perché se un server *stateless* si blocca, basta riavviarlo. Non ho bisogno di ricostruire alcuno stato. Invece se cade un server *stateful*, è necessario ricostruire lo stato delle operazioni in corso per ogni client: operazione molto più complessa. D'altro canto un server *stateful* è usualmente più veloce, anche se più complesso. .. index:: cluster .. _ref_cluster: Cluster -------- I cluster sono utilizzati o per fare elaborazione distribuita, o per fare load balancing. Nel caso si load balancing, le richieste che arrivano dai client sono indirizzate ai diversi server applicativi disponibili. Questo concetto può essere legato a quello di replica. I server applicativi e i database possono essere repliche organizzate in cluster per fare load balancing. Di solito esiste un load balancer (dispatcher) centralizzato che sparpaglia le richieste verso i server applicativi. Questa architettura presenta due problemi: * lo switch può diventare un collo di bottiglia, che strangola le performance; * lo switch può essere un single point of failure. Per risolvere in modo più evoluto questa problematica, si può cercare di affrontarla come un **server distribuito** (*distributed server*). E questo a sua volta può richiedere funzionalità a livello di rete, utilizzando il supporto a sistemi mobili presente in IP versione 6 (MIPv6). **Funzionamento di MIPv6**. In MIPv6, un **mobile node** (MN) ha una *home network* di riferimento, con un indirizzo stabile (*home address*: HoA). La *home network* ha un router speciale, detto **home agent** (HA), che riceve le richieste per *MN* e gliele inoltra. Quando *MN* si stacca dalla home network e si collega ad un'altra rete (*foreign network*), riceve un ulteriore indirizzo (*care-of address*: CoA) che comunica al propio *home agent*. Se un nodo generico (CN) vuole comunicare con *MN*, usa il suo *HoA*, che arriva al *home agent*. Questo reindirizza al *MN* (HoA se è connesso localmente, CoA se è su altra rete). Si può anche avere una ottimizzazione detta *path optimization*. Consiste nel fatto che *HA* passi al chiamante *CN* l'indirizzo reale di destinazione (HoA o CoA che sia), evitando così di gestire in prima persona tutto il traffico in ingresso e uscita. Questa ottimizzazione è rilevante da un punto di vista della implementazione di HA, e di impegno di banda della rete, ma ha notevoli controindicazioni a livello di sicurezza: si espone l'indirizzo reale del destinatario. A questo punto si capisce come si può utilizzare il MIPv6 per implementare un server distribuito. Si assegna un indirizzo univoco al server distribuito (l'equivalente del HoA). Inoltre ogni server componente del sistema distribuito avrà l'equivalente del CoA, uno diverso per ogni componente. A questo punto, con una apposita strategia, i componenti, uno per volta, dichiarano a turno il proprio CoA al home agent. In tal modo le richieste in arrivo vengono sparpagliate dal HA via via verso componenti diversi. In tal modo si ottiene uno sparpagliamento degli indirizzi verso i server applicativi utilizzando un meccanismo di rete MIPv6. Quindi non è necessario aver un apposito (complesso) nodo di load balancing, ma basta utilizzare un (semplice) router home agent. Router che può anche essere facilmente replicato per avere una funzione di resistenza al guasto. ------------------- .. [#] Ricordare che il multiTCP lavora a livello 4. Per farlo usa i campi option del TCP. Questi stessi campi sono usati dai firewall. Quindi se si è con firewall vi possono essere conflitti.