Aller au contenu principal

Vue d'ensemble de la qualité de service

Les politiques de qualité de service (QoS) contrôlent la façon dont DDS delivre les données, offrant un contrôle fin sur la fiabilité, le timing, l'utilisation des ressources, et bien plus.

Pourquoi les QoS ?

Différentes applications ont des besoins differents :

Cas d'usageExigences
Streaming de capteursDébit élevé, quelques pertes acceptables
CommandesLivraison garantie, ordonnées
Synchro d'étatLes retardataires reçoivent l'état courant
Contrôle temps réelBasse latence, suivi des deadlines

Les politiques QoS vous permettent de configurer ces comportements de manière déclarative.

Categories de politiques QoS

+---------------------------------------------------------+
| Groupes de politiques QoS |
+-----------------+-----------------+---------------------+
| Livraison | Timing | Gestion ressources |
| - Reliability | - Deadline | - History |
| - Durability | - Latency Budget| - ResourceLimits |
| - History | - Lifespan | |
+-----------------+-----------------+---------------------+
| Ownership | Ordonnancement | Cyclé de vie |
| - Ownership | - DestinationOrd| - Liveliness |
| - OwnershipStr | - Presentation | - WriterDataLifecycle|
| | | - ReaderDataLifecycle|
+-----------------+-----------------+---------------------+
| Metadonnees : UserData, TopicData, GroupData, Partition |
+---------------------------------------------------------+

Politiques QoS principales

Reliability

Contrôle si la livraison des données est garantie :

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("app")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let topic = participant.topic::<SensorData>("sensors/data")?;

// Best effort - may lose samples (fast)
let writer = topic
.writer()
.qos(QoS::best_effort())
.build()?;

// Reliable - guaranteed delivery with retransmits
let writer = topic
.writer()
.qos(QoS::reliable())
.build()?;

Durability

Contrôle la persistance des données pour les Subscribers qui se connectent en retard :

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("app")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let topic = participant.topic::<SensorData>("sensors/data")?;

// Volatile - no history for late joiners (default)
let writer = topic
.writer()
.qos(QoS::reliable().volatile())
.build()?;

// Transient Local - keep samples in memory for late joiners
let writer = topic
.writer()
.qos(QoS::reliable().transient_local())
.build()?;

// Persistent - survive process restart
let writer = topic
.writer()
.qos(QoS::reliable().persistent())
.build()?;

History

Contrôle le nombre d'échantillons conservés :

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("app")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let topic = participant.topic::<SensorData>("sensors/data")?;

// Keep last N samples per instance
let writer = topic
.writer()
.qos(QoS::reliable().keep_last(10))
.build()?;

// Keep all samples
let writer = topic
.writer()
.qos(QoS::reliable().keep_all())
.build()?;

Compatibilité QoS

Les Writers et Readers doivent avoir des QoS compatibles pour communiquer :

Writer QoS          Reader QoS           Match ?
---------------------------------------------------
reliable() --> reliable() Oui
reliable() --> best_effort() Oui
best_effort() --> best_effort() Oui
best_effort() --> reliable() NON

persistent() --> persistent() Oui
persistent() --> transient_local() Oui
persistent() --> volatile() Oui
transient_local() --> transient_local() Oui
transient_local() --> volatile() Oui
transient_local() --> persistent() NON
volatile() --> volatile() Oui
volatile() --> transient_local() NON

Règle : Le Writer doit offrir au moins ce que le Reader demande.

API fluent Builder

HDDS utilise un patron fluent builder pour les QoS :

use hdds::QoS;

// Start with à preset
let qos = QoS::reliable()
.keep_last(100) // History: keep last 100 samples
.transient_local(); // Durability: cache for late joiners

// Or best effort for speed
let qos = QoS::best_effort()
.keep_last(1) // Minimal history
.volatile(); // No caching

Profils QoS courants

Streaming de capteurs

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("sensor_stream")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let topic = participant.topic::<SensorData>("sensors/imu")?;

// Fast, may lose samples
let writer = topic
.writer()
.qos(QoS::best_effort().keep_last(1))
.build()?;

Synchronisation d'état

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("state_sync")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let topic = participant.topic::<StateData>("system/state")?;

// Reliable with caching for late joiners
let writer = topic
.writer()
.qos(QoS::reliable().keep_last(1).transient_local())
.build()?;

File de commandes

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("command_queue")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let topic = participant.topic::<Command>("robot/commands")?;

// Every command must be delivered
let writer = topic
.writer()
.qos(QoS::reliable().keep_all())
.build()?;

Journal d'événements

use hdds::{Participant, QoS, TransportMode};

let participant = Participant::builder("event_log")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let topic = participant.topic::<AuditEvent>("audit/events")?;

// Persistent event log survives restarts
let writer = topic
.writer()
.qos(QoS::reliable().keep_all().persistent())
.build()?;

Politiques de timing

Deadline

Surveiller la fraîcheur des données :

use hdds::{Participant, QoS, TransportMode};
use std::time::Duration;

let participant = Participant::builder("deadline_example")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let topic = participant.topic::<SensorData>("sensors/data")?;

// Writer must publish within 100ms
let writer = topic
.writer()
.qos(QoS::reliable().deadline(Duration::from_millis(100)))
.build()?;

Liveliness

Detecter les défaillances de Writer :

use hdds::{Participant, QoS, TransportMode};
use std::time::Duration;

let participant = Participant::builder("liveliness_example")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;

let topic = participant.topic::<Heartbeat>("system/heartbeat")?;

// Writer automatically asserts liveliness
// Reader notified if writer stops for 10s
let writer = topic
.writer()
.qos(QoS::reliable().liveliness_automatic(Duration::from_secs(10)))
.build()?;

Résumé des politiques QoS

PolitiqueFonction
reliable() / best_effort()Garantie de livraison
transient_local() / volatile() / persistent()Données historiques
keep_last(n) / keep_all()Buffer d'échantillons
deadline()Suivi du taux de mise à jour
liveliness_*()Détection de défaillance

Dépannage QoS

Pas d'appariement (QoS incompatibles)

Warning: Writer and Reader QoS incompatible

Vérifiez :

  • Reliability : Writer >= Reader
  • Durability : Writer >= Reader
  • Deadline : Writer <= Reader
  • Liveliness : Writer kind >= Reader kind

Deadlines manquees

Warning: Deadline missed

Solutions :

  • Augmenter la période de deadline
  • Réduire le taux de publication
  • Vérifier les problèmes réseau

Prochaines étapes