Skip to content

Commit a8a9cc1

Browse files
Address coments to large message chunking implementation details
1 parent 2251ff3 commit a8a9cc1

File tree

1 file changed

+54
-29
lines changed

1 file changed

+54
-29
lines changed

doc/dev/adr/0020-large-message-chunking.md

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,49 +7,74 @@ Proposed
77
The MQTT protocol has inherent message size limitations imposed by brokers and network constraints. Azure IoT Operations scenarios often require transmitting payloads that exceed these limits (e.g., firmware updates, large telemetry batches, complex configurations). Without a standardized chunking mechanism, applications must implement their own fragmentation strategies, leading to inconsistent implementations and interoperability issues.
88

99
## Decision
10-
We will implement sdk-level message chunking as part of the MQTT layer by using MQTT user properties to carry chunk metadata. This approach will make the chunking mechanism explicit in the SDK rather than hiding it in higher or lower layers.
10+
We will implement sdk-level message chunking as part of the Protocol layer to transparently handle messages exceeding the MQTT broker's maximum packet size.
1111

12-
The chunking mechanism will:
13-
1. Be applied only to MQTT PUBLISH packets
14-
2. Use standardized user properties for chunk metadata:
15-
- `__chunk`: `<original message id>;<chunk index>;<total chunk count>;<full message check sum>`; `<original message id>,<chunk index>` - present for every chunk; `<total chunk count>,<full message check sum>` - present only for the first chunk.
12+
**The chunking mechanism will**:
13+
- Be enabled/disabled by a configuration setting.
14+
- Use standardized user properties for chunk metadata:
15+
- The `__chunk` user property will contain a JSON object with chunking metadata.
16+
- The JSON structure will include:
17+
```json
18+
{
19+
"messageId": "unique-id-for-chunked-message",
20+
"chunkIndex": 0,
21+
"timeout" : "00:00:10",
22+
"totalChunks": 5,
23+
"checksum": "optional-message-hash"
24+
}
25+
```
26+
- `messageId, chunkIndex, timeout` - present for every chunk; `totalChunks, checksum` - present only for the first chunk.
1627

17-
### Protocol Flow
18-
**Sending Process:**
19-
- When a payload exceeds the maximum packet size, the MQTT client intercepts it before transmission
20-
- The message is split into fixed-size chunks (with potentially smaller last chunk)
21-
- Each chunk is sent as a separate MQTT message with the same topic but with chunk metadata.
22-
- Any user properties and additional metadata not mandated by the MQTT protocol to appear in every message, originally set on the initial PUBLISH packet, will be included only in the first chunk.
23-
- QoS settings are maintained across all chunks.
28+
**Chunk size calculation**:
29+
- Maximum chunk size will be derived from the MQTT CONNECT packet's Maximum Packet Size.
30+
- A static overhead value will be subtracted from the Maximum Packet Size to account for MQTT packet headers, topic name, user properties, and other metadata.
31+
- The overhead size will be configurable, large enough to simplify calculations while ensuring we stay under the broker's limit.
2432

25-
**Receiving Process:**
26-
- The MQTT client receives messages and identifies chunked messages by the presence of chunk metadata.
27-
- Chunks are stored in a temporary buffer, indexed by message ID and chunk index.
28-
- When all chunks for a message ID are received, they are reassembled in order and message checksum verified.
29-
- The reconstructed message is then processed as a single message by the application callback.
33+
**Implementation layer**:
34+
- Chunking will be implemented as middleware in the Protocol layer between serialization and MQTT client.
35+
```
36+
Application → Protocol Layer (Serialization) → Chunking Middleware → MQTT Client → Broker
37+
```
38+
- This makes chunking transparent to application code and compatible with all serialization formats.
3039
31-
**Note:**
32-
Chunk size is a three party agreement: *publisher-broker-subscriber*. Publisher can set the chunk size, but it is capped by the subscriber's or broker's maximum packet size which ever is smaller.
33-
34-
## Consequences
40+
- Sending Process:
41+
- When a payload exceeds the maximum packet size, the midlware intercepts it before transmission
42+
- The message is split into fixed-size chunks (with potentially smaller last chunk)
43+
- Each chunk is sent as a separate MQTT message with the same topic but with chunk metadata.
44+
- Effort should be made to minimize user properties copied over to every chunk: first chunk will have full set of original user properties and the rest only thoses that are neccessary to reassamble original message (ex.: ```$partition``` property to support shared subscriptions:).
45+
- QoS settings are maintained across all chunks.
46+
- Receiving Process:
47+
- The Chunking aware client receives messages and identifies chunked messages by the presence of chunk metadata.
48+
- Chunks are stored in a temporary buffer, indexed by message ID and chunk index.
49+
- When all chunks for a message ID are received, they are reassembled in order and message checksum verified.
50+
- The reconstructed message is then processed as a single message by the application.
3551
3652
### Benefits
37-
- **Standards-Based:** Uses existing MQTT features rather than custom transport mechanisms
38-
- **Protocol Transparent:** Makes chunking behavior explicit in the MQTT protocol
3953
- **Property Preservation:** Maintains topic, QoS, and other message properties consistently
4054
- **Network Optimized:** Allows efficient transmission of large payloads over constrained networks
4155
4256
### Implementation Considerations
4357
- **Error Handling:**
44-
- Chunk timeout mechanisms
58+
- Chunk timeout mechanisms, fixed or sliding timeout window approaches can be used (see Chunk Timeout Mechanism Options in Appendix)
4559
- Error propagation to application code
4660
- **Performance Optimization:**
4761
- Concurrent chunk transmission
4862
- Efficient memory usage during reassembly
4963
- **Security:**
50-
- Validate message integrity across chunks
51-
- Prevent chunk injection attacks
64+
- Validate message integrity across chunks and prevent chunk injection attacks (covered if checksumm implemented)
65+
66+
# Appendix
67+
68+
## Chunk Timeout Mechanism Options
69+
70+
1. Fixed Timeout Window
71+
- Set a single timeout period after receiving the first chunk
72+
- If all chunks aren't received within this window, the message is considered failed
73+
- **Pros**: Simple implementation, predictable behavior
74+
- **Cons**: Not adaptive to message size or network conditions
5275
53-
## Open Questions
54-
1. Do we create a new API method (`PublishLargeAsync()`) or use the existing `PublishAsync()` API with transparent chunking for oversized payloads?
55-
2. Chunking and shared subscriptions: How do we handle chunked messages across multiple subscribers?
76+
2. Sliding Timeout Window
77+
- Reset the timeout each time a new chunk arrives
78+
- Only expire the chunked message if there's a long gap between chunks
79+
- **Pros**: Tolerates varying network conditions and delivery rates
80+
- **Cons**: Could keep resources allocated for extended periods

0 commit comments

Comments
 (0)