[ISSUE #305]feat: Introduce Standalone Mode by Allowing Meta Module Disabling#314
[ISSUE #305]feat: Introduce Standalone Mode by Allowing Meta Module Disabling#314HeartLinked wants to merge 11 commits into
Conversation
| enableMultiDispatch = true | ||
| ``` | ||
|
|
||
| ### Deployment Modes |
There was a problem hiding this comment.
It can't be called a deployment mode.
|
|
||
| + Cluster-Ready Mode (Meta Enabled, Default): This is the default and full-featured mode. It relies on a meta service (based on RocketMQ's KV storage) for dynamic configuration, cluster node discovery, and advanced features like Retain Messages and Will Messages. This mode is suitable for production and high-availability environments. | ||
|
|
||
| + Standalone Mode (Meta Disabled): This is a simplified mode designed for single-node deployments or scenarios where advanced features are not required. It operates without any dependency on the meta service, making configuration and deployment much simpler. In this mode, features like Retain Messages and Will Messages are disabled. |
There was a problem hiding this comment.
mqtt proxy is still deployed in a cluster
|
plz commit to the develop branch |
|
|
||
| private boolean enableMetaModule = true; | ||
| private String staticFirstTopics; | ||
| private String localAddress; |
There was a problem hiding this comment.
Why do you need staticFirstTopics and localAddress?
| public CompletableFuture<StoreResult> put(MqttMessageUpContext context, MqttMessage mqttMessage) { | ||
| MqttPublishMessage mqttPublishMessage = (MqttPublishMessage) mqttMessage; | ||
|
|
||
| if (mqttPublishMessage.fixedHeader().isRetain()) { |
There was a problem hiding this comment.
This code can be simplified and less intrusive. For example
if (mqttPublishMessage.fixedHeader().isRetain() && !serviceConf.isEnableMetaModule()) {
logger.error("Client [{}] on topic [{}] tried to publish a Retain Message, but the meta module is disabled. Rejecting request.",
context.getClientId(), mqttPublishMessage.variableHeader().topicName());
MqttRetainException exception = new MqttRetainException("Retain Message feature is disabled.");
CompletableFuture<StoreResult> failedFuture = new CompletableFuture<>();
failedFuture.completeExceptionally(exception);
return failedFuture;
}
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Review by github-manager-bot
Summary
Introduces a Standalone Mode for RocketMQ-MQTT that allows running without the external meta service dependency. This simplifies deployment for users who don't need Retain Messages and Will Messages features.
Findings
-
[Info]
ServiceConf.java— TheenableMetaModuleswitch (default true) withstaticFirstTopicsandlocalAddressconfiguration is a clean approach. Backward compatible since the default preserves existing behavior. -
[Info]
MqttConnectHandler.java— Properly gates Will Message feature behindenableMetaModule. The error logging and connection close on attempted Will Message in standalone mode is correct behavior. -
[Info]
NotifyManager.java— The dual-mode refactoring (dynamic topic refresh from meta vs. static topic list) is well-structured. The local RPC loopback for standalone mode is a reasonable approach. -
[Warning]
MqttPacketDispatcher.java:143-148— The new PUBLISH rejection logic closes the connection for any failed hook result. This is a behavior change that affects both cluster and standalone modes. Consider whether this is too aggressive — a failed hook might be transient and closing the connection could cause unnecessary client reconnects. -
[Warning]
PublishProcessor.java— The retain message rejection when meta is disabled should return a proper MQTT CONNACK/PUBACK error code rather than just logging and silently dropping. MQTT clients expect protocol-level feedback. -
[Info]
MqttRetainException.java— New exception class is clean but missing a newline at end of file (checkstyle may flag this).
Suggestions
- Consider adding integration tests for standalone mode (e.g., verify Will Message is rejected, verify static topics work).
- The PUBLISH rejection in
MqttPacketDispatchershould be reviewed by maintainers to confirm the connection-close behavior is intentional for all hook failure scenarios. - Add a configuration validation check at startup: if
enableMetaModule=false, verifystaticFirstTopicsandlocalAddressare configured.
Automated review by github-manager-bot
This PR introduces a crucial option to run the RocketMQ-MQTT proxy layer in a configuration that does not depend on an external stateful meta service.
The primary motivation is to simplify deployment and reduce operational overhead for users who do not require stateful features like Retain Messages and Will Messages. By disabling this dependency, users can deploy the stateless MQTT proxy cluster without the need to set up, manage, and operate a separate, Raft-based meta cluster.
Key Changes
This feature is implemented through a series of coordinated changes across the common, ds, and cs modules:
The NotifyManager has been refactored to operate in two modes.When meta is disabled, it subscribes to the topics listed in staticFirstTopics at startup, instead of dynamically refreshing from the meta service. The message notification logic (notifyMessage) is adjusted to perform a local RPC loopback to itself, instead of broadcasting to a cluster of nodes.
To ensure system stability, features dependent on the meta module are now gated by the enableMetaModule switch.
How to Configure and Test Standalone Mode
Connect a client with a Will Message set. The server should refuse the connection.
With an active connection, publish a message with the retain flag set to true. The server should close the connection.
Related Issue
fix #305