Vai al contenuto

Differenze tra Webhook e Websocket

Ci sono numerose tecnologie e terminologie che gli sviluppatori incontrano durante il loro percorso, due delle quali sono Webhook e WebSocket. Entrambe sono utilizzate per la comunicazione sul web, ma hanno scopi diversi e funzionano in modi diversi. Questo articolo mira a fornire una comprensione approfondita di entrambe queste tecnologie, delle loro differenze e quando utilizzare ciascuna.

Webhook

I Webhook sono un meccanismo di comunicazione automatica tra applicazioni web, che consente a un sistema di notificare in modo proattivo un altro sistema quando si verificano determinati eventi. Piuttosto che il sistema di destinazione dover interrogare il sistema di origine per aggiornamenti, i webhook inviano una notifica direttamente al sistema di destinazione.

I webhook sono essenzialmente “richieste HTTP innescate da eventi”. E’ quindi un modo per dire a un sistema di “fare questa cosa” automaticamente quando accade qualcosa di rilevante. Sono un mezzo di comunicazione server-to-server. Un webhook viene attivato da un evento in un server e invia dati tramite un URL preconfigurato a un altro server. Quando si verifica un evento specifico su un server, il server invia una richiesta HTTP (POST) all’URL configurato per il webhook. La richiesta conterrà informazioni sull’evento che possono essere utilizzate dal server ricevente.

I webhook sono efficienti per ricevere aggiornamenti in tempo reale e possono essere personalizzati in base a eventi ed esigenze specifiche. Sono comunemente utilizzati in scenari quali l’aggiornamento di un database quando un nuovo utente si registra, la notifica a un server di posta di inviare un’e-mail di benvenuto dopo la registrazione, nellea piattaforma di pagamento per notificare un sistema di e-commerce quando un pagamento è stato completato, in modo che l’ordine possa essere processato immediatamente. o persino l’attivazione di una nuova build in una pipeline di integrazione continua quando una modifica viene inviata a un sistema di controllo delle versioni.

Webhook: l’approccio Pub-Sub

Immaginiamo di essere in un ristorante in attesa del nostro ordine. Un cameriere cammina in giro annunciando gli ordini completati. Questo sistema “shout-out” è simile al funzionamento dei webhook. I webhook sono un metodo leggero per un’applicazione (publisher) per notificare un’altra applicazione (subscriver) su eventi specifici.

Ecco la ripartizione:

  1. Impostazione: il subscriver fornisce al publisher un URL, il suo “indirizzo di ascolto”.
  2. Trigger di eventi: quando si verifica un evento predefinito nell’applicazione del publisher (ad esempio, la registrazione di un nuovo utente), viene attivata una notifica webhook.
  3. Consegna: il publisher invia una richiesta HTTP (solitamente un POST) all’URL del subscriver , riportando nel corpo della richiesta le informazioni rilevanti sull’evento.
  4. Elaborazione: il subscriver riceve la notifica ed elabora le informazioni di conseguenza, innescando potenzialmente azioni all’interno della propria applicazione.

Pensiamo ai webhook come a un sistema di notifiche push: il publisher invia aggiornamenti al subscriver quando accade qualcosa di degno di nota. Questa comunicazione unidirezionale rende i webhook semplici e scalabili, ideali per situazioni in cui il subscriver deve solo reagire agli eventi e non necessita di una comunicazione continua avanti e indietro.

Ecco un esempio simile di implementazione del modello Pub-Sub in JavaScript. Utilizzeremo classi ES6 per dimostrare il pattern di Pub-Sub e come gestire gli eventi tra Publisher e Subscriber.

Il publisher

  • La classe ProductPublisher gestisce una lista di Subscriber.
  • I metodi subscribe e unsubscribe consentono di aggiungere e rimuovere Subscriber.
  • Il metodo notify invia i dati dell’evento a tutti i Subscriber.
  • Il metodo updateProduct simula l’aggiornamento di un prodotto e notifica i Subscriber.
class ProductPublisher {
    constructor() {
        this.subscribers = [];
    }

    // Iscrivere un Subscriber
    subscribe(subscriber) {
        this.subscribers.push(subscriber);
    }

    // Disiscrivere un Subscriber
    unsubscribe(subscriber) {
        this.subscribers = this.subscribers.filter(sub => sub !== subscriber);
    }

    // Notificare tutti i Subscriber dell'evento
    notify(eventData) {
        this.subscribers.forEach(subscriber => subscriber.update(eventData));
    }

    // Metodo per simulare l'aggiornamento del prodotto
    updateProduct(productName) {
        const eventData = `Il prodotto ${productName} è stato aggiornato.`;
        this.notify(eventData);
    }
}

Il subscriver

  • Le classi CatalogUpdater, CustomerNotifier, e Logger rappresentano i Subscriber che reagiscono agli eventi.
  • Ogni Subscriber implementa il metodo update, che viene chiamato dal Publisher con i dati dell’evento.
class CatalogUpdater {
    update(eventData) {
        console.log(`Catalogo aggiornato: ${eventData}`);
    }
}

class CustomerNotifier {
    update(eventData) {
        console.log(`Notifica ai clienti: ${eventData}`);
    }
}

class Logger {
    update(eventData) {
        console.log(`Log dell'evento: ${eventData}`);
    }
}

Ora mettiamo tutto insieme per vedere il sistema Pub-Sub in azione.

  • Creiamo un’istanza di ProductPublisher e diversi Subscriber.
  • Iscriviamo i Subscriber al Publisher.
  • Quando chiamiamo updateProduct, il Publisher invia notifiche a tutti i Subscriber, i quali reagiscono stampando messaggi specifici.
// Creare il Publisher (gestore degli aggiornamenti prodotto)
const productPublisher = new ProductPublisher();

// Creare alcuni Subscriber
const catalogUpdater = new CatalogUpdater();
const customerNotifier = new CustomerNotifier();
const logger = new Logger();

// Iscrivere i Subscriber al Publisher
productPublisher.subscribe(catalogUpdater);
productPublisher.subscribe(customerNotifier);
productPublisher.subscribe(logger);

// Simulare l'aggiornamento di un prodotto
productPublisher.updateProduct('Super Smartphone 3000');

Vantaggi

  • Decoupling: Il Publisher non ha bisogno di conoscere i dettagli dei Subscriber.
  • Modularità: Nuovi Subscriber possono essere facilmente aggiunti e rimossi senza modificare il Publisher.
  • Semplicità: L’uso delle classi e dei metodi rende il codice facile da leggere e mantenere.

WebSocket

I WebSocket stabiliscono un canale di comunicazione persistente e bidirezionale tramite un’unica connessione realizzata tra due porte TCP da un client (browser) a un server. A differenza dell’HTTP, una connessione WebSocket rimane aperta, consentendo ai dati di fluire senza problemi tra le parti. Entrambe le estremità di una connessione WebSocket possono inviare dati all’altra, rendendola ideale per il trasferimento di dati in tempo reale. Questa connessione rimane aperta finché entrambe le parti ne hanno bisogno, consentendo lo scambio di dati in tempo reale in entrambe le direzioni, più simile a una linea telefonica dedicata per una conversazione continua.

I WebSocket sono molto utili quando si lavora su applicazioni di streaming di dati server-client a bassa latenza. Offrono un enorme vantaggio in termini di velocità, specialmente quando i dati vengono inviati dal server al client. Sono comunemente utilizzati in applicazioni in tempo reale come live chat, analisi in tempo reale, giochi multigiocatore e ambienti di editing collaborativo come Google Docs.

Ecco uno sguardo al funzionamento dei WebSocket:

  1. Handshake: il client avvia una connessione inviando una richiesta speciale di handshake al server.
  2. Upgrade: il server riconosce la richiesta e aggiorna la connessione da HTTP a una connessione WebSocket. Ciò crea un canale persistente e bidirezionale.
  3. Flusso di dati: una volta connessi, sia il client che il server possono inviare e ricevere messaggi di dati in qualsiasi momento. I messaggi vengono solitamente inviati in un formato come JSON per facilitarne l’analisi.
  4. Chiusura: quando la comunicazione non è più necessaria, entrambe le parti possono avviare un handshake di chiusura per terminare correttamente la connessione.

Ecco un esempio di richiesta handshake via HTTP

Richiesta di Handshake: Il client invia una richiesta di handshake al server tramite HTTP. La richiesta contiene un’intestazione Upgrade che indica che il client desidera stabilire una connessione WebSocket.

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

Risposta di Handshake: Il server risponde con un’intestazione di upgrade se accetta la richiesta, indicando che la connessione è stata aggiornata da HTTP a WebSocket.

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: <accept-key>

Il Sec-WebSocket-Accept è una chiave calcolata dal server che conferma che ha ricevuto e accettato la chiave del client.

Implementazione del client in JS

// Creare una connessione WebSocket
const socket = new WebSocket('ws://example.com/chat');

// Gestire l'apertura della connessione
socket.addEventListener('open', (event) => {
  console.log('Connessione aperta');
  socket.send('Hello Server!');
});

// Gestire la ricezione di messaggi
socket.addEventListener('message', (event) => {
  console.log('Messaggio ricevuto:', event.data);
});

// Gestire la chiusura della connessione
socket.addEventListener('close', (event) => {
  console.log('Connessione chiusa');
});

// Gestire gli errori
socket.addEventListener('error', (event) => {
  console.error('Errore WebSocket:', event);
});

Implementazione del server in Node.js

onst WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
  console.log('Client connesso');

  ws.on('message', (message) => {
    console.log('Messaggio ricevuto:', message);
    ws.send('Messaggio ricevuto: ' + message);
  });

  ws.on('close', () => {
    console.log('Client disconnesso');
  });

  ws.on('error', (error) => {
    console.error('Errore WebSocket:', error);
  });
});

Differenze tra webhook e websocket

Sebbene sia i Webhook che i WebSocket siano utilizzati per la comunicazione sul Web, hanno scopi diversi e funzionano in modi diversi. Ecco alcune differenze chiave:

  • Comunicazione: i webhook sono un metodo di comunicazione unidirezionale (dal server al client), mentre i WebSocket sono un metodo di comunicazione bidirezionale.
  • Connessione: i webhook utilizzano una nuova richiesta HTTP per ogni messaggio, mentre i WebSocket utilizzano un’unica connessione persistente per più messaggi.
  • Caso d’uso: i webhook sono ideali per le notifiche di eventi, mentre i WebSocket sono ideali per le applicazioni in tempo reale.

Quando utilizzarli?

  • Utilizzare i webhook quando:
    • Abbiamo bisogno di una soluzione semplice e scalabile per le notifiche unidirezionali
    • Il subscriver deve solo reagire agli eventi e non necessita di aggiornamenti costanti
    • Sono sufficienti brevi intervalli di scambio dati
  • Utilizzare i WebSocket quando:
    • È necessaria una comunicazione bidirezionale in tempo reale tra client e server
    • Per il funzionamento dell’applicazione è necessario uno scambio costante di dati (ad esempio, chat, modifica collaborativa)
    • La bassa latenza (ritardo minimo) è fondamentale