Connettività e protocolli · intermedio

Un dispositivo IoT deve usare MQTT o HTTP?

MQTT e HTTP a confronto per i dispositivi IoT: overhead, push contro polling, modello di connessione, batteria, MQTT su WebSocket e quando conviene REST.

Yellow and white electrical wires

Foto: Patrick Turner / Unsplash

Dopo aver letto questo articolo saprai:

  • Spiegare come una connessione MQTT persistente si differenzia dalla richiesta-risposta HTTP per il traffico dei dispositivi
  • Stimare dove ciascun protocollo spende byte ed energia, e come i comandi arrivano al dispositivo
  • Decidere quando HTTP o REST sono la scelta migliore e quando aiuta MQTT su WebSocket
In questa pagina
  1. In cosa differiscono i due modelli?
  2. Quanto overhead aggiunge ciascuno?
  3. Come raggiunge il dispositivo ciascuno?
  4. Quale è migliore per i dispositivi a batteria?
  5. Quando HTTP è la scelta migliore?
  6. E MQTT su WebSocket?
  7. Per continuare

MQTT e HTTP funzionano entrambi su TCP e possono trasportare la stessa lettura in JSON, ma organizzano la conversazione in modo diverso. Con MQTT un dispositivo apre una connessione verso un broker, la tiene aperta e pubblica e riceve su topic con un nome. Con HTTP un client invia una richiesta a un server e ottiene una risposta; il server non può parlare per primo. Questa sola differenza decide gran parte dei compromessi descritti sotto.

La risposta breve. Usa MQTT quando i dispositivi inviano spesso messaggi piccoli, quando il cloud deve spingere comandi o configurazioni ai dispositivi senza aspettare che li chiedano, quando più applicazioni consumano gli stessi dati o quando i collegamenti sono inaffidabili. Usa HTTP (di solito una REST API) quando i dispositivi trasmettono di rado, quando soprattutto scaricano cose come configurazioni o firmware, quando ti integri con servizi web esistenti o quando non vuoi gestire un broker. Molte flotte usano entrambi: MQTT per telemetria e comandi, HTTPS per il download del firmware e il provisioning.

MQTTHTTP (REST)
SchemaPublish-subscribe tramite brokerRichiesta-risposta fra client e server
ConnessioneDi lunga durata, mantenuta con pingPer richiesta, o riusata finché c’è traffico
Raggiungere il dispositivoIl broker invia sui topic sottoscrittiIl dispositivo deve interrogare o tenere aperta una richiesta
Intestazione minimaHeader fisso di 2 byteRiga di richiesta e header testuali
Opzioni di consegnaQoS 0, 1, 2; messaggi retained; Last WillCodici di stato; i tentativi spettano al client
SpecificaOASIS MQTT 3.1.1 e 5.0IETF RFC 9110 e RFC correlate

In cosa differiscono i due modelli?

HTTP è definito come un protocollo richiesta-risposta senza stato: ogni richiesta porta tutto ciò che serve al server, e la risposta chiude lo scambio. Un dispositivo che vuole comunicare una temperatura invia una POST a un URL; uno che vuole un’impostazione invia una GET. Il server non prende mai l’iniziativa. È un modello semplice da capire, mettere in cache, bilanciare e diagnosticare, ed è per questo che domina il web.

MQTT è publish-subscribe. Dispositivi e applicazioni si connettono a un broker come client, pubblicano messaggi su topic come site1/pump3/pressure e sottoscrivono schemi di topic. Chi pubblica non sa chi riceve i messaggi, e un nuovo consumatore può sottoscrivere senza alcuna modifica sul dispositivo. Il broker mantiene uno stato di sessione per ogni client: secondo la specifica MQTT 5.0 comprende le sottoscrizioni del client e i messaggi QoS 1 e 2 ancora da consegnargli. Il protocollo è con stato per progetto, e quello stato vive nel broker.

Quanto overhead aggiunge ciascuno?

MQTT è stato progettato per pacchetti piccoli. Ogni pacchetto di controllo inizia con un header fisso di almeno due byte, un byte di tipo e una “remaining length” a lunghezza variabile, e un ping di keep-alive è solo quell’header. Una PUBLISH aggiunge il nome del topic e, per QoS 1 o 2, un identificativo di pacchetto prima del payload.

Una richiesta HTTP/1.1 porta su ogni messaggio una riga di richiesta e header testuali (host, tipo di contenuto, lunghezza, autorizzazione), che per una lettura di dieci byte possono pesare molte volte il payload. HTTP/2 comprime gli header ripetuti con HPACK, il che riduce la distanza su una connessione lunga ma aggiunge un proprio framing.

Il costo maggiore spesso è la connessione, non gli header. Aprire TCP e negoziare TLS richiede diversi round trip più uno scambio di certificati di solito molto più grande di una lettura del sensore. Un dispositivo che tiene aperta una connessione MQTT lo paga una volta. Uno che apre una nuova connessione HTTPS per ogni lettura lo paga ogni volta. HTTP/1.1 usa per default connessioni persistenti, quindi un client che invia una raffica di richieste può riusarne una, ma server e proxy chiudono le connessioni inattive, e i dispositivi che dormono fra un invio e l’altro di solito si riconnettono comunque. AWS riassume la differenza per il proprio servizio indicando per MQTT overhead di protocollo e consumo energetico più bassi rispetto a HTTPS.

Come raggiunge il dispositivo ciascuno?

Qui MQTT vince nettamente. Un dispositivo che ha sottoscritto devices/42/commands riceve un comando appena il broker lo ottiene, sulla connessione che ha già. Con HTTP il dispositivo deve chiedere: interroga a intervalli (lento a reagire, dispendioso quando nulla cambia) oppure tiene aperta una richiesta in long polling (che è di nuovo una connessione persistente, costruita con parti non pensate per questo).

La differenza si vede nelle funzioni delle piattaforme. AWS IoT Core permette ai client HTTPS solo di pubblicare, mentre i client MQTT pubblicano e sottoscrivono, e solo con MQTT offre il rilevamento della disconnessione e i messaggi conservati per un dispositivo rimasto offline. MQTT aggiunge anche il Last Will, un messaggio che il broker pubblica quando un client cade senza salutare, e i messaggi retained, che consegnano subito a un nuovo sottoscrittore l’ultimo valore noto.

Quale è migliore per i dispositivi a batteria?

Dipende da quanto spesso il dispositivo comunica. Un dispositivo che trasmette ogni pochi secondi o deve accettare comandi in qualsiasi momento sta molto meglio con una sola connessione MQTT: ogni messaggio costa pochi byte, e l’intervallo di keep-alive, che MQTT esprime in secondi, si può regolare secondo i timeout NAT che la rete consente.

Un dispositivo che si sveglia una volta all’ora, invia una lettura e torna a dormire è un caso diverso. Tenere viva una connessione TCP per un’ora di sonno di solito non è possibile, quindi si riconnette in ogni caso, e il confronto si riduce a CONNECT e PUBLISH di MQTT contro una singola POST HTTP su una nuova sessione TLS. La differenza è piccola, e a decidere può essere la semplicità lato server. Per i dispositivi più limitati, su NB-IoT o su radio a batteria, la risposta migliore può non essere nessuno dei due: CoAP su UDP evita del tutto TCP.

Quando HTTP è la scelta migliore?

  • Invii rari e nessun comando. Un contatore che carica i dati una volta al giorno guadagna poco da un broker.
  • Scaricare invece che ricevere. Immagini firmware, certificati e file di configurazione si adattano alla richiesta-risposta, con range, cache e content delivery network già pronti.
  • Integrazione con servizi web. Webhook, API di terze parti e funzioni serverless parlano HTTP in modo nativo, e ogni sviluppatore ne conosce gli strumenti.
  • Nessun broker da gestire. Un piccolo progetto con un solo back end può non giustificare la gestione di un broker e della sua sicurezza.
  • Semantica richiesta-risposta stretta. Quando il dispositivo ha bisogno di una risposta precisa a una domanda precisa, i codici di stato HTTP sono più chiari delle proprietà richiesta-risposta di MQTT 5.

MQTT è la scelta migliore per flotte che richiedono comandi e stato in tempo reale, per distribuire i dati a più consumatori e per collegamenti cellulari o satellitari inaffidabili, dove il suo modello di sessione e QoS ti evita di scrivere una tua logica di ritrasmissione.

E MQTT su WebSocket?

La specifica MQTT definisce WebSocket come trasporto: i pacchetti MQTT viaggiano in frame WebSocket binari, e la connessione negozia il nome di sottoprotocollo mqtt. Il protocollo WebSocket parte come richiesta HTTP e poi aggiorna la connessione, quindi attraversa proxy e firewall che lasciano passare solo traffico web, di solito sulla porta 443. AWS IoT Core, per esempio, accetta MQTT su WebSocket sulla porta 443 con le stesse operazioni di pubblicazione e sottoscrizione di MQTT semplice.

Prevalgono due usi. Le dashboard nel browser non possono aprire socket TCP grezzi, quindi sottoscrivono i dati dei dispositivi in tempo reale tramite WebSocket. I dispositivi dietro reti aziendali che bloccano la porta 8883, che la specifica indica come registrata presso IANA per MQTT su TLS, possono comunque raggiungere un broker. Il costo è un upgrade HTTP all’apertura e qualche byte di framing WebSocket per pacchetto, che conta poco una volta stabilita la connessione.

Per continuare

Argomenti: MQTT, HTTP, REST, protocolli, confronto

Diagramma