我试图通过WiFi和MQTT协议编写控制机器人群的应用程序。我已经进行了一些测试,以测量它是否足够快我的应用程序。我想有一个控制循环(从PC到机器人和返回的消息)平均不超过25-30ms。
我使用Paho Java客户端编写了一个应用程序,它运行在两台机器上。当在topic1上收到消息时,它会发布到topic2。 Topic2由第二台机器订阅,而第二台机器又发布到topic1。
topic1 topic1
M1---------> broker ---------> M2
topic2 topic2
M1 <-------- broker <--------- M2
当所有发布和订阅都使用QoS 0时,循环时间平均约为12毫秒。但是,我想使用QoS 1来保证发送到机器人的命令将始终到达目的地。当我测试循环时间时,它平均在250ms左右。
是什么导致这么多时间的增加?根据我的理解,如果没有传输错误,交换的数据包数量只会与QoS1加倍(每个消息都有从代理向客户端发送的PUBACK,请参阅http://www.hivemq.com/mqtt-essentials-part-6-mqtt-quality-of-service-levels/)。
我可以以某种方式缩短这段时间吗?我尝试过Mosquitto和Apache Apollo经纪人,两者都复制了相同的结果。
修改
我稍微改变了测试程序。现在,我有两个mqtt客户端实例在同一台机器上运行。一个是发布者,另一个是订阅者。 Publisher以10ms的间隔发送1000条消息,如下所示:
Client publisher = new Client(url, clientId+"pub", cleanSession, quietMode, userName, password);
Client subscriber = new Client(url, clientId+"sub", cleanSession, quietMode, userName, password);
subscriber.subscribe(pubTopic, qos);
while (counter < 1000) {
Thread.sleep(10,0);
String time = new Timestamp(System.currentTimeMillis()).toString();
publisher.publish(pubTopic, qos, time.getBytes());
counter++;
}
虽然订阅者只是等待消息并测量时间:
public void messageArrived(String topic, MqttMessage message) throws MqttException {
// Called when a message arrives from the server that matches any
// subscription made by the client
Timestamp tRec = new Timestamp(System.currentTimeMillis());
String timeSent = new String(message.getPayload());
Timestamp tSent = Timestamp.valueOf(timeSent);
long diff = tRec.getTime() - tSent.getTime();
sum += diff;
counter++;
if (counter == 1000) {
double avg = sum / 1000.0;
System.out.println("avg time: " + avg);
}
}
Broker(具有默认配置的mosquitto)在同一本地网络中的单独机器上运行。我取得的成果比以前更奇怪。现在,具有QoS 1的消息需要大约8-9ms才能到达订户。使用QoS 2,它大约20ms。但是,使用QoS 0,我得到平均值。时间从100ms到甚至250ms!我猜错误是在我的测试方法中的某个地方,但我无法看到。
答案 0 :(得分:3)
不需要保留QoS 0消息 - 它们可以完全保留在内存中。
为了能够确保QoS 1(和QoS 2)传递,消息需要以某种形式保留。这会在简单的网络传输时间内为消息增加额外的处理时间。
答案 1 :(得分:0)
2个完全不同的代理实现显示相同结果的含义可能是代码的客户端需要花时间来响应ack数据包。
您是否正在对onMessage回调中的传入方法进行所有处理?如果是这样,这项工作将在与可能延迟响应的所有MQTT协议处理相同的线程上完成。对于高容量/高速消息处理,通常使用的模式是仅使用onMessage回调对传入消息进行排队,以便另一个线程实际处理。