[英]How to implement a request-response pattern with paho mqtt java?
我想使用Paho MQTT Java并实现一些“请求-响应”模式。 我的意思是,在某些情况下,客户端必须与服务器对话并期望对特定请求的特定答复。 感觉这个库有匹配请求和响应所需的一切,但我不能把它们放在一起。
我发现我可以通过deliveryComplete
检索令牌,并且可以对这个令牌执行setActionCallback
。 但首先,我不完全确定“动作”是什么意思。 那么,如果它意味着我认为的意思,如何从那里获得对我的请求的实际响应?
sampleClient.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
System.out.println(topic);
System.out.println("setCallback: "+ message.toString());
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
System.out.println(token.getMessageId());
token.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
var response = asyncActionToken.getResponse();
try {
System.out.println(new String(response.getPayload()));
} catch (MqttException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
}
});
}
});
MQTT 对于任何类型的 1 Request - 1 Response 来说都是多余的……这就是 API 的用途。 MQTT 最适合一个节点向一个或多个接入主题的节点发送数据。 发送节点(发布者)不需要知道任何接收节点(订阅者)......他们只需要就使用的主题达成一致。
话虽如此,您可以实现“查询”发布,并查找您将订阅的“回复”MQTT 消息。 过去我已经这样做了,多个节点可以从知道回复是什么中受益。 所以它可能看起来像这样:发布 - q/system/status
和订阅r/system/status
或r/system/#
。
MQTT 协议中没有端到端的传递通知。 仅调用传递完成回调以通知消息已在发布客户端和代理之间传输,它没有说明消息是否已传递给任何向下的 stream 订阅者(订阅给定主题的许多其他客户端可能为 0 )。
一旦消息到达代理,它甚至可以排队等待具有持久 session 的离线客户端。
即使假设只有一个客户端接收到消息,任何回复都将是一个完全独立的消息,不链接到第一个请求。
MQTT 本身并不是一个请求/响应系统,例如 HTTP,它是一种将消息发送到 0 的方式,以发送给订阅给定主题的许多客户端。
MQTT v5 开始向 MQTT 引入请求/响应的概念,但即便如此,它也只是 header 中的一个额外可选插槽,用于包含一个要回复的主题。 您可以在消息 header 中设置排序规则 ID,以将响应消息链接到请求。
这可以使用 MQTT5 来完成。
它是这样工作的:假设您有两个 MQTT 客户端,其中一个充当服务器。 客户端1,客户端2(服务器)。 client1 在消息属性中发布带有响应主题的消息。 客户端 2 接收消息读取消息属性并发布关于该主题的响应客户端 1 获取关于响应主题的消息。
这是一个小实现:
使用以下依赖项:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-paho-mqtt5</artifactId>
<version>3.17.0</version>
</dependency>
客户 1 发布:
public void sendMessage(String messageStr){
MqttMessage message = new MqttMessage();
MqttProperties properties = new MqttProperties();
properties.setResponseTopic("response");
properties.setCorrelationData("correlation".getBytes());
message.setProperties(properties);
message.setPayload(messageStr.getBytes());
message.setQos(1);
message.setRetained(true);
try {
client.publish("test",message);
} catch (MqttException e) {
e.printStackTrace();
}
}
客户端 2(服务器)订阅者消息监听器:
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.mqttv5.client.IMqttClient;
import org.eclipse.paho.mqttv5.client.IMqttMessageListener;
import org.eclipse.paho.mqttv5.common.MqttMessage;
import org.eclipse.paho.mqttv5.common.packet.MqttProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Slf4j
@Component
public class MessageListener implements IMqttMessageListener {
@Autowired
private IMqttClient client;
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
log.info("Topic : {}, Message: {}", topic,message.toString());
MqttProperties properties = new MqttProperties();
if(message.getProperties()!=null && StringUtils.hasText(message.getProperties().getResponseTopic())){
MqttMessage responseMessage = new MqttMessage();
properties.setCorrelationData(message.getProperties().getCorrelationData());
responseMessage.setProperties(properties);
responseMessage.setPayload("Response".getBytes());
responseMessage.setQos(1);
responseMessage.setRetained(true);
client.publish(message.getProperties().getResponseTopic(),responseMessage);
}
}
}
然后客户端 1 应该订阅主题“响应”以接收来自客户端 2 的响应。
这里有更多关于这个:
http://www.steves-internet-guide.com/mqttv5-request-response/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.