Topic · Reference

QoS Cookbook

Alle 22 QoS-Policies aus DDS 1.4 §2.2.3 — Spec-Anker, Default-Werte, Code-Pfade in zerodds-qos, und konkrete Rezepte für die häufigsten Production-Setups (Telemetry-Sink, Discovery-Tuning, Late-Joiner, Exclusive-Failover, Hard-Realtime).

Spec: DDS 1.4 §2.2.3 · 22 Policies Crate: zerodds-qos Status: ✓ RC3 voll spec-konform

Was sind QoS-Policies

QoS-Policies sind das deklarative Vertragsmodell von DDS. Jede Entity — DomainParticipant, Topic, Publisher/Subscriber, DataWriter/DataReader — trägt einen QoS-Block, der das Verhalten am Wire (Reliability, Order, Durability) und die Match-Regeln (Partition, Ownership, Liveliness) festlegt.

Beim Discovery werden die QoS-Blöcke ausgetauscht und im Match-Test verglichen (RxO — "Requested vs. Offered"). Inkompatible Policies blocken den Match und triggern RequestedIncompatibleQosStatus bzw. OfferedIncompatibleQosStatus — siehe DCPS Listener-API.

Im ZeroDDS-Code leben die Policy-Typen in zerodds-qos; die DCPS-API-Aggregate (DataWriterQos, DataReaderQos, …) leben in zerodds-dcps §qos.rs.

Reference statt Rezept? Die QoS Reference kaut jede der 22 Policies einzeln durch — Spec-Anker, Felder, Defaults, Mutability nach enable, RxO-Verhalten — plus die vollständige Compatibility-Matrix der 9 RxO-Pairs und die Within-Entity-Konsistenzregeln.

Die 22 Policies

Vollständige Tabelle nach DDS 1.4 §2.2.3 mit Default-Werten und ZeroDDS-Crate-Pfad. RxO-Spalte: ✓ = wird beim Match geprüft (Mismatch blockt Discovery-Match).

Policy Spec § Default RxO Repo
UserDataQosPolicy §2.2.3.1 empty crates/qos/src/policies/generic_data.rs
TopicDataQosPolicy §2.2.3.2 empty crates/qos/src/policies/generic_data.rs
GroupDataQosPolicy §2.2.3.3 empty crates/qos/src/policies/generic_data.rs
DurabilityQosPolicy §2.2.3.4 Volatile crates/qos/src/policies/durability.rs
DurabilityServiceQosPolicy §2.2.3.5 KeepLast(1) crates/qos/src/policies/durability_service.rs
PresentationQosPolicy §2.2.3.6 Instance/false/false crates/qos/src/policies/presentation.rs
DeadlineQosPolicy §2.2.3.7 INFINITE crates/qos/src/policies/deadline.rs
LatencyBudgetQosPolicy §2.2.3.8 0 ns crates/qos/src/policies/latency_budget.rs
OwnershipQosPolicy §2.2.3.9 Shared crates/qos/src/policies/ownership.rs
OwnershipStrengthQosPolicy §2.2.3.10 0 crates/qos/src/policies/ownership_strength.rs
LivelinessQosPolicy §2.2.3.11 Automatic/INFINITE crates/qos/src/policies/liveliness.rs
TimeBasedFilterQosPolicy §2.2.3.12 0 ns crates/qos/src/policies/time_based_filter.rs
PartitionQosPolicy §2.2.3.13 [""] crates/qos/src/policies/partition.rs
ReliabilityQosPolicy §2.2.3.14 Writer Reliable · Reader BestEffortcrates/qos/src/policies/reliability.rs
TransportPriorityQosPolicy §2.2.3.15 0 crates/qos/src/policies/transport_priority.rs
LifespanQosPolicy §2.2.3.16 INFINITE crates/qos/src/policies/lifespan.rs
DestinationOrderQosPolicy §2.2.3.17 ByReceptionTimestamp crates/qos/src/policies/destination_order.rs
HistoryQosPolicy §2.2.3.18 KeepLast(1) crates/qos/src/policies/history.rs
ResourceLimitsQosPolicy §2.2.3.19 1000 / 10 / 100 crates/qos/src/policies/resource_limits.rs
EntityFactoryQosPolicy §2.2.3.20 autoenable_created_entities=truecrates/qos/src/policies/entity_factory.rs
WriterDataLifecycleQosPolicy §2.2.3.21 autodispose=true crates/qos/src/policies/data_lifecycle.rs
ReaderDataLifecycleQosPolicy §2.2.3.22 INFINITE / INFINITE crates/qos/src/policies/data_lifecycle.rs

Vollständige Spec-Coverage gegen DDS 1.4 §2.2.3: zerodds-dcps-1.4 Spec-Coverage →

Cookbook-Rezepte

Konkrete Policy-Kombinationen für die häufigsten Production-Setups. Jedes Rezept zeigt die relevanten Policies, einen Code-Snippet und die typischen Trade-Offs.

1 · Telemetry-Sink — Fire-and-Forget

Wann: Hochfrequenz-Sensoren (≥100 Hz), Verlust von Einzel-Samples tolerierbar, Konsumenten kommen und gehen.

let writer_qos = DataWriterQos {
    reliability: ReliabilityQosPolicy {
        kind: ReliabilityKind::BestEffort,
        ..Default::default()
    },
    durability: DurabilityQosPolicy {
        kind: DurabilityKind::Volatile,
    },
    history: HistoryQosPolicy {
        kind: HistoryKind::KeepLast,
        depth: 1,
    },
    ..Default::default()
};

▶ Runnable example: qos-cookbook

Trade-Off: Kein ACK-Verkehr, kein Retransmit. Late-Joiner sehen nichts. Wer das Sample verliert, hat es verloren.

2 · Late-Joiner mit Last-Value-Cache

Wann: Config-/State-Topics (Setpoints, Modes), Konsumenten starten asynchron und müssen den letzten Wert beim Beitritt sehen.

let writer_qos = DataWriterQos {
    reliability: ReliabilityQosPolicy {
        kind: ReliabilityKind::Reliable,
        max_blocking_time: Duration::from_millis(100),
    },
    durability: DurabilityQosPolicy {
        kind: DurabilityKind::TransientLocal,
    },
    history: HistoryQosPolicy {
        kind: HistoryKind::KeepLast,
        depth: 1,
    },
    ..Default::default()
};

▶ Runnable example: qos-cookbook

Trade-Off: Writer hält 1 Sample pro Instance im Cache; Speicher steigt mit Instance-Anzahl. Reader-Side DurabilityKind::TransientLocal muss matchen, sonst kein Cache-Replay.

3 · Exclusive-Ownership Failover

Wann: Hot-Standby-Schreiber (Primary + Backup), nur ein Writer pro Instance darf zeitgleich publizieren.

let primary_qos = DataWriterQos {
    ownership: OwnershipQosPolicy {
        kind: OwnershipKind::Exclusive,
    },
    ownership_strength: OwnershipStrengthQosPolicy { value: 100 },
    liveliness: LivelinessQosPolicy {
        kind: LivelinessKind::ManualByTopic,
        lease_duration: Duration::from_secs(1),
    },
    ..Default::default()
};
// Backup: gleiche Topic + ownership=Exclusive, strength=50

▶ Runnable example: qos-cookbook

Trade-Off: Lease-Duration definiert Failover-Latenz (Sekunden). Beide Writer müssen assert_liveliness() in der App ausführen.

4 · Hard-Realtime — Deadline + LatencyBudget

Wann: Control-Loops mit harten Zyklus-Garantien, deadline-misses sind Fehler-Signale, latenz-Budget zur Hinweis-Optimierung.

let reader_qos = DataReaderQos {
    deadline: DeadlineQosPolicy {
        period: Duration::from_millis(10), // 100 Hz
    },
    latency_budget: LatencyBudgetQosPolicy {
        duration: Duration::from_micros(500),
    },
    reliability: ReliabilityQosPolicy {
        kind: ReliabilityKind::Reliable,
        max_blocking_time: Duration::from_millis(1),
    },
    history: HistoryQosPolicy {
        kind: HistoryKind::KeepLast,
        depth: 4, // 40 ms headroom
    },
    ..Default::default()
};

▶ Runnable example: qos-cookbook

Trade-Off: RequestedDeadlineMissedStatus muss vom Reader-Listener gehandelt werden. LatencyBudget ist ein Hint, kein Match-Effekt — wird vom Transport-Scheduler ausgewertet.

5 · Partitioned Multi-Tenant Topics

Wann: Mehrere Tenants teilen sich ein Topic-Set, dürfen sich aber nicht gegenseitig matchen (z.B. customer-A/odom vs. customer-B/odom).

let publisher_qos = PublisherQos {
    partition: PartitionQosPolicy {
        names: vec!["customer-A".into()],
    },
    ..Default::default()
};
// Subscriber-Side: partition = ["customer-A"] oder ["customer-*"] (Pattern)

▶ Runnable example: qos-cookbook

Trade-Off: Partition matched über String-Comparison (mit POSIX-fnmatch-Pattern). Discovery-Verkehr läuft trotzdem über die gleiche Domain — Partition ist Match-Filter, keine Network-Isolation.

Cross-Vendor-Interop

QoS-Policies werden im Discovery (SEDP) als ParameterList-Block ausgetauscht (DDSI-RTPS §8.5.4). ZeroDDS sendet und empfängt alle 22 Policies wire-konform — verifiziert gegen Cyclone DDS, FastDDS und RTI Connext (siehe DDSI-RTPS 2.5 Spec-Coverage).

Bekannte Gotchas im Cross-Vendor-Setup:

  • Reliability-Defaults divergieren: ZeroDDS folgt der Spec (Writer = Reliable, Reader = BestEffort). RTI Connext setzt Reader-Default ebenfalls auf Reliable. Wenn ein RTI-Reader gegen einen Cyclone- oder ZeroDDS-Writer matched, achte auf explizite Setting.
  • Partition-Default-Wert: Spec sagt [""] (Default-Partition mit leerem String). Manche Vendoren senden [] (leere Sequence). ZeroDDS akzeptiert beides als Default.
  • Liveliness-Lease in Sub-Millisekunden: Cyclone DDS rundet auf 1 ms ab. ZeroDDS behält Mikrosekunden-Auflösung. Bei sehr kurzem Lease in Cross-Vendor-Setups setze ≥1 ms.