Apache NiFi se connecte à MQTT avec deux processeurs standard : ConsumeMQTT s'abonne à un filtre de topic et transforme les messages reçus en FlowFiles, et PublishMQTT envoie le contenu d'un FlowFile sur un topic. La configuration minimale tient en un Broker URI comme tcp://broker.connectmq.com:1883, un Topic Filter ou Topic, une QoS et — pour ConsumeMQTT — un Max Queue Size. Tout le reste (TLS, identifiants, sessions, records, cluster) détermine si le flux est fiable en production.
Ce tutoriel passe en revue chaque propriété importante, puis construit et teste un flux qui consomme de la télémétrie JSON, la filtre en SQL et republie des alertes sur MQTT.
Lancer NiFi pour les tests
NiFi 2.x tourne sur Java 21 ; l'image Docker officielle est le moyen le plus rapide d'obtenir l'interface :
docker run --name nifi -p 8443:8443 \
-e SINGLE_USER_CREDENTIALS_USERNAME=admin \
-e SINGLE_USER_CREDENTIALS_PASSWORD=change-me-to-12-chars-min \
-d apache/nifi:latestOuvrez https://localhost:8443/nifi (acceptez le certificat auto-signé) et connectez-vous. Figez un tag d'image précis pour tout ce que vous gardez. Le mot de passe doit comporter au moins 12 caractères, sinon le conteneur refuse de démarrer.
Propriétés de ConsumeMQTT
Glissez un processeur sur le canvas, cherchez ConsumeMQTT et ouvrez ses propriétés. Voici celles à régler dans chaque flux :
| Propriété | Exemple | Remarques |
|---|---|---|
| Broker URI | tcp://broker.connectmq.com:1883 | Schémas tcp, ssl, ws, wss. Une liste séparée par des virgules offre un failover entre brokers. |
| MQTT Specification Version | v5.0 | AUTO tente la 5.0 puis se replie. Figez la version testée. |
| Client ID | (vide) | Vide, un UUID est généré — le choix sûr en cluster. |
| Group ID | (vide) ou nifi-ingest | Si renseigné, NiFi s'abonne via une shared subscription ($share/<group>/<filter>). |
| Topic Filter | testmqtt/nifi/+/telemetry | Un seul filtre ; + et # autorisés. Testez-le avec le topic matcher. |
| Quality of Service (QoS) | 1 | 1 pour les données qu'on ne peut pas perdre silencieusement. |
| Max Queue Size | 1000 | Tampon mémoire entre le callback MQTT et l'exécution du processeur. |
| Username / Password | $MQTT_USER / $MQTT_PASS | Utilisez un paramètre NiFi (sensible) plutôt que de saisir le secret dans le processeur. |
| Session state | Clean Session | Resume Session conserve l'abonnement et les messages QoS 1/2 en attente entre reconnexions. |
Le processeur écrit chaque message sur la relation Message et ajoute les attributs mqtt.broker, mqtt.topic, mqtt.qos, mqtt.isDuplicate et mqtt.isRetained. Sans record reader, chaque message MQTT devient un FlowFile dont le contenu est le payload brut.
Regrouper avec des records
Un FlowFile par message convient pour quelques messages par seconde et devient du gaspillage au-delà. Réglez Record Reader sur un JsonTreeReader et Record Writer sur un JsonRecordSetWriter : ConsumeMQTT écrit alors tous les messages reçus depuis la dernière exécution sous forme de records dans un seul FlowFile. Avec Add attributes as fields à true, chaque record reçoit aussi les champs _topic, _qos, _isDuplicate et _isRetained, ce qui évite de perdre le topic quand des messages de nombreux appareils partagent un FlowFile. Les payloads que le reader ne sait pas parser partent sur la relation parse.failure — dirigez-la vers un funnel ou un log pour rendre visibles les appareils défaillants ; voir erreurs de parsing JSON pour les causes typiques.
TLS
Passez l'URI à ssl://broker.connectmq.com:8883 (ou wss://broker.connectmq.com:8084/mqtt derrière des proxys qui n'autorisent que HTTPS) et réglez SSL Context Service sur un StandardSSLContextService. Pour un broker doté d'un certificat publiquement reconnu, le truststore peut pointer vers le fichier cacerts de la JVM ; pour une CA privée, importez la CA dans un truststore dédié. Si le handshake échoue, comparez avec un test openssl s_client — tester une connexion MQTT TLS donne les commandes.
Propriétés de PublishMQTT
PublishMQTT partage les propriétés de connexion (Broker URI, version, Client ID, identifiants, SSL) et ajoute :
| Propriété | Exemple | Remarques |
|---|---|---|
| Topic | testmqtt/nifi/alerts | Accepte l'Expression Language, p. ex. ${mqtt.topic:replace('telemetry','echo')} |
| Quality of Service (QoS) | 1 | Accepte aussi l'Expression Language |
| Retain Message | false | true uniquement pour les topics d'état |
| Record Reader / Record Writer | JsonTreeReader / JsonRecordSetWriter | Si renseignés, chaque record est publié comme un message MQTT distinct |
| Message Expiry Interval | 300 sec | MQTT 5 uniquement ; le broker supprime le message s'il n'est pas livré dans ce délai |
Sans record reader, tout le contenu du FlowFile constitue un seul payload. Vérifiez sa taille par rapport à la taille maximale de paquet de votre broker — un FlowFile fusionné de 5 Mo envoyé comme un seul message MQTT est un accident fréquent. Le calculateur de taille de paquet aide à estimer l'overhead.
Les publications en échec partent sur failure. Rebouclez cette relation vers PublishMQTT avec retry ou pénalité pour qu'un incident bref du broker ne perde pas de données.
Construire un flux testé
Objectif : consommer la télémétrie de testmqtt/nifi/<device>/telemetry, tout conserver et publier une alerte quand la température dépasse 30.
ConsumeMQTT ──Message──▶ QueryRecord ──hot──▶ PublishMQTT (testmqtt/nifi/alerts)
│ └──original──▶ PutDatabaseRecord / PublishKafka / PutFile
└──parse.failure──▶ LogAttribute- ConsumeMQTT avec les propriétés ci-dessus, Record Reader
JsonTreeReader, Record WriterJsonRecordSetWriter, Add attributes as fieldstrue. - QueryRecord avec le même reader/writer et une propriété dynamique nommée
hot:
SELECT _topic, device, temperature, ts
FROM FLOWFILE
WHERE temperature > 30- PublishMQTT sur la relation
hot, Topictestmqtt/nifi/alerts, QoS 1, avec Record Reader/Writer pour que chaque mesure chaude soit publiée comme un message à part. - Envoyez la relation
originalvers votre stockage : PostgreSQL avec PutDatabaseRecord, Kafka avec PublishKafka, ou simplement PutFile pendant les tests.
Par défaut, QueryRecord envoie aussi un FlowFile vide sur hot quand rien ne correspond. Mettez Include Zero Record FlowFiles à false pour que seuls les lots contenant au moins une mesure chaude atteignent PublishMQTT.
Tester de bout en bout
Démarrez tous les processeurs, puis ouvrez un subscriber sur le topic d'alerte :
mosquitto_sub -h broker.connectmq.com -p 1883 -t 'testmqtt/nifi/alerts' -vPubliez une mesure normale et une mesure chaude :
mosquitto_pub -h broker.connectmq.com -p 1883 -q 1 \
-t testmqtt/nifi/press-7/telemetry \
-m '{"device":"press-7","temperature":24.1,"ts":1760700000}'
mosquitto_pub -h broker.connectmq.com -p 1883 -q 1 \
-t testmqtt/nifi/press-7/telemetry \
-m '{"device":"press-7","temperature":33.8,"ts":1760700005}'Le terminal 1 doit afficher exactement une alerte contenant "temperature":33.8 et "_topic":"testmqtt/nifi/press-7/telemetry". Dans NiFi, faites un clic droit sur la file après ConsumeMQTT et choisissez List queue (ou ouvrez Data Provenance) pour voir les deux FlowFiles et leurs attributs mqtt.*. Publiez ensuite not json sur le même topic et vérifiez qu'il arrive sur parse.failure au lieu de casser le flux. Vous pouvez faire de même depuis le client MQTT en ligne si vous préférez le navigateur.
Suivre en direct les topics de test NiFi
ConsumeMQTT en cluster
Dans un cluster NiFi, chaque nœud exécute chaque processeur. Pour ConsumeMQTT, cela veut dire que chaque nœud s'abonne — et que chaque nœud reçoit chaque message. Choisissez l'un de ces deux schémas :
- Nœud primaire uniquement. Dans l'onglet Scheduling du processeur, réglez Execution sur Primary node. Simple et ordonné, mais un seul nœud fait tout le travail MQTT et il existe une courte interruption lors d'un changement de primaire.
- Shared subscription. Définissez un Group ID (par exemple
nifi-ingest) et laissez le Client ID vide pour que chaque nœud obtienne un ID unique. Le broker répartit les messages entre les nœuds ; voir les shared subscriptions MQTT. L'ordre n'est alors garanti que par nœud, pas globalement.
Ne mettez jamais le même Client ID fixe sur tous les nœuds : le broker n'autorise qu'une connexion par client ID, et les nœuds se volent la session en boucle.
Sessions, QoS et redémarrages
Avec Clean Session et QoS 0, tout ce qui est publié pendant l'arrêt de NiFi est perdu. Pour une ingestion qui ne tolère pas de perte, utilisez QoS 1, un Client ID fixe par consommateur, Resume Session et — en MQTT 5 — un Session Expiry Interval assez long pour couvrir les fenêtres de maintenance. Le broker met alors les messages en file pendant l'interruption et les livre à la reconnexion de NiFi. Cela suppose un broker qui conserve les sessions persistantes ; l'endpoint de test partagé broker.connectmq.com ne stocke pas de sessions hors ligne, vérifiez donc ce comportement sur votre propre instance privée de broker (voir sessions persistantes).
Erreurs courantes
| Message ou symptôme | Cause | Correctif |
|---|---|---|
Not authorized to connect (5) | Identifiants erronés ou pas de droit CONNECT | Testez le même login avec mosquitto_sub, puis vérifiez le paramètre sensible |
Connection lost (32109) en boucle | Client ID en double ou timeout de keep-alive | Laissez le Client ID vide ou rendez-le unique par nœud |
MqttException: ... SSL / erreurs de handshake | Truststore absent, mauvais port pour ssl:// | Utilisez le port 8883 avec ssl:// et configurez le SSL Context Service |
| Back pressure sur la file sortante | L'aval est plus lent que l'entrée MQTT | Activez les records, ajoutez des seuils de back pressure, montez en charge via shared subscriptions |
Retrouvez les reason codes numériques dans l'outil des reason codes MQTT.
Les deux processeurs MQTT de NiFi sont simples, mais les flux de production tiennent aux détails : TLS et identifiants paramétrés, records plutôt qu'un FlowFile par message, une stratégie de cluster claire et une configuration de session adaptée à la quantité de données que vous pouvez vous permettre de perdre. Testez chaque flux avec un second client MQTT avant de lui confier de vrais appareils.
Questions fréquentes
ConsumeMQTT prend-il en charge MQTT 5 ?
Oui. Les versions actuelles de NiFi proposent la propriété « MQTT Specification Version » avec AUTO, v3.1.0, v3.1.1 et v5.0. En v5.0, vous disposez aussi de réglages MQTT 5 comme le session expiry interval sur ConsumeMQTT et le message expiry sur PublishMQTT.
Pourquoi chaque nœud du cluster NiFi reçoit-il le même message MQTT ?
Chaque nœud exécute sa propre instance de ConsumeMQTT avec son propre abonnement. Planifiez le processeur sur le nœud primaire uniquement, ou définissez un Group ID pour que les nœuds rejoignent une shared subscription MQTT et que le broker répartisse les messages.
Comment regrouper des messages MQTT dans un seul FlowFile ?
Définissez un Record Reader et un Record Writer sur ConsumeMQTT (par exemple JsonTreeReader et JsonRecordSetWriter). Les messages reçus entre deux exécutions sont alors écrits comme records dans un seul FlowFile au lieu d'un FlowFile par message.



