繁体   English   中英

如何使用 paho mqtt java 实现请求-响应模式?

[英]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/statusr/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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM