Hi all,
I have a reliable writer connected to a reliable reader and everything works fine.
However, when I add a slow Best Effort reader to the mix, the reliable reader starts losing messages.
I can see that the writer's write buffer (200) is full and the best effort reader's receive buffer (500) is also full and the writer is dropping messages because there is no room left in the write buffer.
But the reason I used best effort reliability on the slow reader is so that wouldn't happen. Am I missing something?
Does the fact that there is a reliable reader present prevent the best effort reader from using best effort reliability and forcing a reliable connection?
Also, they are all using KEEP_LAST_HISTORY_QOS
Is there a way to make the best effort reader not block the reliable writer in this scenario?
I fed your question into our Connext Chatbot verbatim. Here's what it replied with:
No—the presence of a reliable reader does not turn the Best Effort reader into a reliable one. A reliable DataWriter can match both kinds of readers, but it runs the reliability protocol only for its reliable matches. The slow Best Effort reader does not ACK samples or cause retransmissions.
What you are seeing is instead a consequence of the reliable writer’s shared writer-side resources, especially its RTPS reliable-writer send window.
With a
RELIABLEDataWriter andKEEP_LASThistory:data_writer_protocol.rtps_reliable_writer.max_send_window_sizeis finite and that send window becomes full,write()can block until samples are protocol-ACKed by the reliable reader(s), or untilreliability.max_blocking_timeexpires.KEEP_LAST, Connext can replace older samples in the writer history. If the reliable reader has not received those samples yet, it will observe loss.So the slow Best Effort reader’s full receive queue should cause that reader to drop data; it should not directly hold up reliable delivery. But its traffic can still consume shared transport/network capacity, CPU, or writer scheduling capacity enough that the reliable reader falls behind. Then the writer’s finite send window/history limits cause the reliable reader to lose older samples.
Recommended approach
1. Keep the slow reader Best Effort
That is correct. Do not expect it to participate in reliable ACK/NACK behavior.
2. Prevent the reliable writer’s send window from throttling
write()For a
RELIABLE + KEEP_LASTwriter, configure the reliable-writer send window as unlimited if your design accepts bounded loss of older samples under overload:<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://community.rti.com/schema/7.7.0/rti_dds_qos_profiles.xsd" version="7.7.0"> <qos_library name="MyQosLibrary"> <qos_profile name="ReliableKeepLastNoSendWindowBlock"> <datawriter_qos> <reliability> <kind>RELIABLE_RELIABILITY_QOS</kind> <max_blocking_time> <sec>0</sec> <nanosec>0</nanosec> </max_blocking_time> </reliability> <history> <kind>KEEP_LAST_HISTORY_QOS</kind> <depth>200</depth> </history> <data_writer_protocol> <rtps_reliable_writer> <min_send_window_size> <value>LENGTH_UNLIMITED</value> </min_send_window_size> <max_send_window_size> <value>LENGTH_UNLIMITED</value> </max_send_window_size> </rtps_reliable_writer> </data_writer_protocol> </datawriter_qos> </qos_profile> </qos_library> </dds>With the send window disabled, a
RELIABLE + KEEP_LASTwriter does not block because of a full send window. It can still overwrite old samples once its configured history/resource limits are reached—so this protects the publisher’s timing, not every historical sample.3. Size the writer history for the reliable reader’s worst-case lag
If the reliable reader must receive every sample during a burst,
KEEP_LASTdepth 200 must cover its maximum backlog:[ \text{required depth} \ge \text{publish rate} \times \text{maximum reliable-reader delay} ]
Also check
RESOURCE_LIMITS.max_samplesandmax_samples_per_instance; those can cap the effective writer cache independently ofHISTORY.depth.4. Isolate the slow Best Effort consumer if it competes for bandwidth
If the slow reader is on a constrained link, consider one of these architectures:
TIME_BASED_FILTER.This avoids the Best Effort stream consuming enough shared network or host resources to make the reliable reader fall behind.
Important distinction
You cannot simultaneously guarantee every sample to the reliable reader and guarantee that the writer will never be delayed or constrained by that reader. If the reliable reader cannot keep up indefinitely, you must choose between:
RELIABLE + KEEP_ALL, sufficient resources, and possible writer blocking; orRELIABLE + KEEP_LAST, sufficiently large depth, and acceptance that older samples may be overwritten during overload.For your stated goal—do not let the slow Best Effort reader interfere—the Best Effort reader is already configured correctly. Focus on the reliable writer’s send-window configuration, writer-history sizing, and isolation of shared bandwidth/resources.
Sources: