使用 MQTT 共享订阅,订阅主题上的消息只会发送到订阅客户端中的一个。那么,群组中的其他客户端也订阅了同一主题,如何接收到该消息呢?
使用 MQTT 共享订阅,订阅主题的消息只会发送到其中一个订阅客户端。
正确。通过正常(非共享)订阅,消息将发送给所有订阅者;对于共享订阅,它们会发送给一位订阅者。
在引入共享订阅之前,很难处理需要多个服务器(用于容错、负载平衡等)但只想处理每条消息一次的情况。共享订阅提供了实现此目的的简单方法。
那么,群组中的其他客户端也订阅了同一个主题,他们如何接收到该消息呢?
如果他们订阅相同的共享订阅(具有相同的
ShareName
),那么只有一个人会收到该消息;这是设计使然。如果您希望他们所有人都收到消息,则不要使用共享订阅。或者,您可以根据规范:建立多个订阅(因此所有订阅者都会收到消息,但只有一个订阅者处理它 - 但请注意“可以”)
如果客户端拥有共享订阅和非共享订阅,并且一条消息与两者都匹配,则客户端将因其拥有非共享订阅而收到该消息的副本。消息的第二个副本将传递给共享订阅的订阅者之一,这可能会导致第二个副本发送给该客户端。
Java Paho (1.2.5) 客户端中有一个有趣的错误,该错误阻止使用包含通配符的共享主题(
#
、+
)https://github.com/eclipse/paho.mqtt.java/问题/827
长话短说,这行不通:
mqttClient.subscribe("$share/group/some_topic/#", 1, (topic, message) -> System.out.println(topic));
相反,需要使用回调:
mqttClient.subscribe("$share/group/some_topic/#", 1);
mqttClient.setCallback(new MqttCallback() {
@Override
public void connectionLost(final Throwable cause) {
}
@Override
public void messageArrived(final String topic, final MqttMessage message) throws Exception {
System.out.println(topic);
}
@Override
public void deliveryComplete(final IMqttDeliveryToken token) {
}
});