Ingestion et messaging¶
Le pipeline d'ingestion est le premier maillon critique : il doit absorber des milliers de connexions simultanées, survivre aux pics, et transmettre les événements sans perte ni duplication.
MQTT en production : scaler au-delà d'un broker unique¶
Un broker MQTT open source standard (Mosquitto) tient quelques milliers de connexions. Dès que le parc dépasse 10 000 appareils ou que la haute disponibilité est requise, il faut passer à un broker conçu pour le clustering.
EMQX¶
EMQX est un broker MQTT écrit en Erlang/OTP, le même runtime que RabbitMQ. Sa particularité : le modèle acteur d'Erlang gère chaque connexion dans un processus léger indépendant, ce qui donne une résilience naturelle aux pannes partielles.
Caractéristiques clés :
- Clustering natif par Mnesia (base de données distribuée Erlang)
- 100 millions de connexions simultanées sur un cluster de 20 nœuds
- Dashboard web intégré, API REST pour la gestion
- Règles de routage internes (Rule Engine) vers Kafka, InfluxDB, webhooks
- Protocoles supportés : MQTT 3.1/3.1.1/5.0, MQTT-SN, CoAP, LwM2M
Configuration cluster EMQX (3 nœuds) :
# emqx.conf — nœud 1
node:
name: emqx@10.0.1.1
cookie: "secret_cluster_cookie"
cluster:
name: iot_prod
discovery_strategy: static
static:
seeds:
- "emqx@10.0.1.1"
- "emqx@10.0.1.2"
- "emqx@10.0.1.3"
listeners:
tcp:
default:
bind: "0.0.0.0:1883"
max_connections: 1000000
ssl:
default:
bind: "0.0.0.0:8883"
ssl_options:
cacertfile: "/etc/emqx/certs/ca.crt"
certfile: "/etc/emqx/certs/server.crt"
keyfile: "/etc/emqx/certs/server.key"
verify: verify_peer
VerneMQ¶
VerneMQ est un autre broker MQTT Erlang, plus orienté opérateur avec un système de plugins Lua. Il est particulièrement adapté aux télécoms et aux plateformes multi-tenant.
Kafka et Redpanda comme bus d'événements¶
MQTT résout l'ingestion (connexions persistantes, QoS, rétention de messages). Mais il n'est pas conçu pour le traitement en aval : pas de partitionnement par clé, pas de replay, pas de groupes de consommateurs avec offsets.
C'est le rôle de Kafka (ou de son équivalent compatible Redpanda).
Rôle de Kafka dans le pipeline IoT¶
flowchart LR
subgraph "Appareils"
D1[Device 001]
D2[Device 002]
D3[Device 003]
end
subgraph "Ingestion MQTT"
B[EMQX cluster\n3 nœuds]
BRIDGE[EMQX Rule Engine\nMQTT → Kafka bridge]
end
subgraph "Bus Kafka"
T1[Topic\niot.telemetry.temperature]
T2[Topic\niot.telemetry.pressure]
T3[Topic\niot.events.alerts]
end
subgraph "Consommateurs"
C1[Stream processor\nFlink]
C2[Sink InfluxDB\nKafka Connect]
C3[Service alertes]
C4[Archive S3]
end
D1 -->|MQTT TLS| B
D2 -->|MQTT TLS| B
D3 -->|MQTT TLS| B
B --> BRIDGE
BRIDGE --> T1
BRIDGE --> T2
BRIDGE --> T3
T1 --> C1
T1 --> C2
T2 --> C1
T2 --> C2
T3 --> C3
T1 --> C4
T2 --> C4 Partitionnement par device¶
Le partitionnement est la clé de la scalabilité Kafka. Pour l'IoT, la règle est simple : partitionner par device ID.
Cela garantit que tous les messages d'un même capteur arrivent dans le même ordre au même consommateur. Avec 100 partitions et 10 000 devices, chaque partition traite en moyenne 100 devices.
Exemple de producer Kafka (Python confluent-kafka) :
from confluent_kafka import Producer
import json, time
conf = {
'bootstrap.servers': 'kafka1:9092,kafka2:9092,kafka3:9092',
'acks': 'all', # durabilité maximale
'compression.type': 'lz4',
'batch.size': 65536, # 64 Ko par batch
'linger.ms': 5 # attendre 5 ms pour remplir le batch
}
producer = Producer(conf)
def publish_telemetry(device_id: str, payload: dict):
producer.produce(
topic='iot.telemetry',
key=device_id.encode(), # clé de partitionnement
value=json.dumps(payload).encode(),
timestamp=int(time.time() * 1000)
)
producer.poll(0) # déclenche les callbacks non-bloquant
Redpanda : Kafka sans ZooKeeper¶
Redpanda est un broker compatible API Kafka, réécrit en C++. Ses avantages pour l'IoT :
- Démarrage en une seule commande (
docker run redpandadata/redpanda) - Pas de ZooKeeper ni de KRaft à gérer
- Latence médiane 2-3× plus faible que Kafka en workload IoT typique
- Consommation mémoire réduite de 40 % environ
Il est 100 % compatible avec l'API Kafka 3.x : les producteurs et consommateurs existants fonctionnent sans modification.
Back-pressure et contrôle de flux¶
Le back-pressure est le mécanisme par lequel un consommateur lent signale à l'ensemble de la chaîne qu'il est saturé, afin d'éviter la perte de données.
Sources de back-pressure dans un pipeline IoT¶
- Pic de reconnexion : après une coupure réseau, tous les devices se reconnectent simultanément et envoient leur backlog store-and-forward.
- Consommateur lent : une requête d'écriture InfluxDB prend 200 ms à la place de 10 ms en raison d'un index fragmenté.
- Traitement lourd : un job Flink exécute une jointure complexe qui ralentit la consommation du topic Kafka.
Stratégies de gestion¶
| Mécanisme | Description | Brique |
|---|---|---|
| Offset lag monitoring | Surveiller le retard des consommateurs Kafka | Kafka / Redpanda metrics |
| Consumer group throttling | Limiter le débit d'un groupe consommateur | max.poll.records, fetch.max.bytes |
| Topic retention | Kafka conserve les messages N heures pour permettre le rattrapage | retention.ms |
| Circuit breaker | Couper le flux vers un sink défaillant et rerouter | Kafka Connect / custom |
| MQTT QoS 1 + clean session false | Garantir la remise même si le broker redémarre | EMQX |
| Flow control MQTT 5.0 | Le broker envoie un DISCONNECT avec Quota Exceeded | EMQX + MQTT 5.0 |
Comparaison MQTT broker vs Kafka¶
| Dimension | MQTT (EMQX cluster) | Kafka / Redpanda |
|---|---|---|
| Modèle | Pub/sub orienté connexion | Log distribué avec offsets |
| Protocole client | MQTT, CoAP, LwM2M | Kafka protocol (TCP binaire) |
| Rétention des messages | Session / QoS seulement | Jours ou semaines (configurable) |
| Replay | Non (sauf MQTT 5.0 retained) | Oui, depuis n'importe quel offset |
| Partitionnement | Par topic uniquement | Par topic + clé (partition key) |
| Nombre de consommateurs | Illimité (fan-out natif) | Limité par nb partitions / groupe |
| Latence typique | < 10 ms | 5-50 ms (batch) |
| Cas d'usage IoT | Ingestion devices → broker | Bus inter-services, traitement, archive |
| Complexité opérationnelle | Modérée | Élevée (mais Redpanda simplifie) |
| Débit max testé | 5M msg/s (cluster 20 nœuds) | 10M msg/s (cluster 10 nœuds) |
Règle d'or : MQTT pour la connexion device-to-cloud, Kafka pour tout ce qui vient après.
Sérialisation des messages¶
Le format de sérialisation a un impact direct sur le débit et la bande passante.
| Format | Taille typique (100 champs) | Lisibilité | Schema évolution | Usage IoT |
|---|---|---|---|---|
| JSON | 2-5 Ko | Humain | Flexible | Debug, prototypage |
| MessagePack | 1-2 Ko | Binaire | Flexible | Devices contraints |
| Avro | 200-500 o | Binaire | Schema Registry | Pipeline Kafka industriel |
| Protobuf | 150-400 o | Binaire | Rétrocompatible | Haute performance |
| CBOR | 800-1 500 o | Binaire | Flexible | Embedded + CoAP |
Pour un pipeline IoT en production, Avro avec Schema Registry Confluent (ou Karapace pour Redpanda) est le standard : il valide les messages à l'écriture et garantit la compatibilité lors des évolutions de schéma.
Ce qu'il faut retenir¶
- EMQX cluster + MQTT 5.0 couvre l'ingestion jusqu'à plusieurs millions de devices.
- Kafka (ou Redpanda) prend le relais comme bus inter-services avec replay et partitionnement.
- Le back-pressure doit être anticipé dès la conception : offset lag, retention, QoS.
Chapitre suivant : Stockage time-series — choisir et configurer la base de données adaptée aux séries temporelles IoT.