乐闻世界logo
搜索文章和话题

What are MQTT's Retained Messages? How to use them?

2月21日 15:44

MQTT's Retained Messages is a special message mechanism that allows the Broker to persist the latest message for new subscribers to receive.

Concept of Retained Messages

Definition

Retained messages are messages persisted by the Broker. When a new client subscribes to the topic, the Broker immediately sends the retained message to that client.

Purpose

  • State Synchronization: New subscribers can immediately get the latest state
  • Initialization Data: Provide initial data for newly connected clients
  • State Recovery: Help clients quickly recover to the latest state
  • Reduce Requests: Avoid clients actively requesting the latest state

How Retained Messages Work

Setting Retained Messages

Set the Retain flag when publishing messages:

shell
PUBLISH Packet Parameters: - Topic: Topic name - Payload: Message content - QoS: QoS level - Retain: true (set as retained message)

Storage of Retained Messages

  • Storage Location: Broker memory or persistent storage
  • Storage Quantity: Only one latest message per topic
  • Storage Overwrite: Newly published retained messages overwrite previous ones

Sending Retained Messages

When a client subscribes to a topic:

  1. Client sends SUBSCRIBE packet
  2. Broker checks if the topic has a retained message
  3. If yes, immediately sends the retained message to the client
  4. Then sends subsequent new messages

Characteristics of Retained Messages

1. One Message Per Topic

  • Rule: Only one latest retained message per topic
  • Overwrite Mechanism: Newly published retained messages replace previous ones
  • Clear Mechanism: Publishing an empty message (empty Payload) can clear retained messages

2. QoS Level

  • Inheritance: Retained message QoS level is determined at publish time
  • Subscription Limit: QoS level received by subscribers is limited by subscription QoS settings
  • QoS Rule: Actual QoS = min(publish QoS, subscribe QoS)

3. Persistence

  • Memory Storage: Default storage in memory
  • Persistent Storage: Can be configured to persist to disk
  • Broker Restart: Persisted retained messages still exist after Broker restart

4. Message Order

  • Sending Order: Retained messages are sent before normal messages
  • Subscription Timing: Sent only once at subscription time
  • Subsequent Messages: Retained messages are not sent repeatedly

Use Cases

1. Device State Synchronization

shell
Scenario: Temperature Sensor Retained Topic: sensor/123/temperature Retained Message: {"value": 25.5, "unit": "C", "timestamp": 1234567890} New subscriber subscribes to sensor/123/temperature Immediately receives latest temperature value

2. Configuration Information Publishing

shell
Scenario: Device Configuration Retained Topic: config/device/123 Retained Message: {"mode": "auto", "interval": 60} New device comes online and subscribes to configuration topic Immediately gets latest configuration

3. System Status Broadcasting

shell
Scenario: System Status Retained Topic: system/status Retained Message: {"status": "running", "version": "1.0.0"} New client subscribes to system status Immediately gets current system status

4. Switch State

shell
Scenario: Smart Switch Retained Topic: switch/123/state Retained Message: {"state": "on"} New subscriber immediately gets switch state

Code Examples

Python (paho-mqtt)

python
import paho.mqtt.client as mqtt import json import time def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") # Subscribe to topic client.subscribe("sensor/+/temperature") def on_message(client, userdata, msg): print(f"Received: {msg.topic} - {msg.payload.decode()}") print(f"Retained: {msg.retain}") # Publish retained message client = mqtt.Client() client.connect("broker.example.com", 1883, 60) # Publish retained message (retain=True) message = {"value": 25.5, "unit": "C", "timestamp": int(time.time())} client.publish("sensor/123/temperature", json.dumps(message), retain=True) # Clear retained message (publish empty message) # client.publish("sensor/123/temperature", "", retain=True) client.disconnect() # Subscriber subscriber = mqtt.Client() subscriber.on_connect = on_connect subscriber.on_message = on_message subscriber.connect("broker.example.com", 1883, 60) subscriber.loop_forever()

JavaScript (MQTT.js)

javascript
const mqtt = require('mqtt'); // Publish retained message const publisher = mqtt.connect('mqtt://broker.example.com'); publisher.on('connect', () => { console.log('Publisher connected'); // Publish retained message (retain: true) const message = JSON.stringify({ value: 25.5, unit: 'C', timestamp: Date.now() }); publisher.publish('sensor/123/temperature', message, { retain: true }); // Clear retained message (publish empty message) // publisher.publish('sensor/123/temperature', '', { retain: true }); publisher.end(); }); // Subscriber const subscriber = mqtt.connect('mqtt://broker.example.com'); subscriber.on('connect', () => { console.log('Subscriber connected'); subscriber.subscribe('sensor/+/temperature'); }); subscriber.on('message', (topic, message) => { console.log(`Received: ${topic} - ${message.toString()}`); console.log(`Retained: ${message.retain}`); });

Best Practices

1. Retained Message Design

  • State Information: Retained messages should represent current state
  • Clear and Concise: Message content should be concise and easy to parse
  • Include Timestamp: Facilitates judging the age of messages
  • Version Control: Can include version information

2. Topic Naming

shell
Recommended Format: - sensor/{device_id}/temperature - config/{device_id} - status/{system_id} Avoid Using: - Wildcard topics (cannot publish to wildcard topics) - Overly complex topic structures

3. Message Size

  • Limit Size: Retained messages should not be too large
  • Recommended Size: Usually less than 1KB
  • Broker Limitations: Be aware of Broker limitations on message size

4. QoS Selection

  • General State: QoS 0
  • Important State: QoS 1
  • Critical State: QoS 2

5. Clear Mechanism

  • Active Clearing: Publish empty message to clear retained messages
  • Regular Cleanup: Regularly check and clean up expired retained messages
  • Lifecycle Management: Set reasonable lifecycle for retained messages

Considerations

  1. Memory Usage: Retained messages consume Broker memory, large numbers may affect performance

  2. Persistence Configuration: If retained messages need to exist after Broker restart, configure persistence

  3. Message Updates: Frequent updates to retained messages increase Broker burden

  4. Subscription Timing: Retained messages are only sent at subscription time, not repeatedly

  5. QoS Limitation: QoS level received by subscribers is limited by subscription QoS settings

  6. Empty Message Clearing: Publishing empty message (empty Payload) can clear retained messages

Retained Messages vs Last Will

FeatureRetained MessagesLast Will
Trigger TimingAt subscriptionAt abnormal disconnection
Message SourcePublisher setsClient sets
Storage LocationBrokerBroker
RecipientNew subscribersClients subscribed to that topic
Message QuantityOne per topicOne per client
Clear MethodPublish empty messageNormal disconnect or reconnect

Limitations of Retained Messages

  1. One Per Topic: Each topic can only retain one message, cannot save historical messages
  2. Memory Usage: Large numbers of retained messages consume significant memory
  3. Real-time: Retained messages may not be the latest (depends on publish frequency)
  4. No History: Cannot get historical state changes
  5. Depends on Broker: Completely relies on Broker reliability

MQTT Retained Messages is a very important mechanism in IoT applications. Proper use can effectively implement state synchronization and initialization, improving user experience and system reliability.

标签:MQTT