java - AWS JAVA IoT 客户端重新连接和超时
问题描述
我在 CONNECTED/DISCONNECTED 主题上使用 IoT 规则(从这里开始)。所以我想在设备连接或断开连接时收到电子邮件。在我的设备上,我在启动时运行下一个代码(仅在启动时):
iotClient = new AWSIotMqttClient(Configuration.IOT_CLIENT_ENDPOINT,
deviceId,
keyStore,
keystorePass);
iotClient.setKeepAliveInterval(1200000); //20 minutes (maximum)
iotClient.connect();
但我得到了非常奇怪的行为。我有 3 台设备,在每台设备上我都得到了这个堆栈跟踪,但由于不同的原因:
[pool-8-thread-1] com.amazonaws.services.iot.client.core.AwsIotConnection.onConnectionSuccess Connection successfully established
[pool-8-thread-1] com.amazonaws.services.iot.client.core.AbstractAwsIotClient.onConnectionSuccess Client connection active: <client ID>
[pool-8-thread-1] com.amazonaws.services.iot.client.core.AwsIotConnection.onConnectionFailure Connection temporarily lost
[pool-8-thread-1] com.amazonaws.services.iot.client.core.AbstractAwsIotClient.onConnectionFailure Client connection lost: <client ID>
[pool-8-thread-1] com.amazonaws.services.iot.client.core.AwsIotConnection$1.run Connection is being retried
[pool-8-thread-1] com.amazonaws.services.iot.client.core.AwsIotConnection.onConnectionSuccess Connection successfully established
[pool-8-thread-1] com.amazonaws.services.iot.client.core.AbstractAwsIotClient.onConnectionSuccess Client connection active: <client ID>
有时由于 DUPLICATE_CLIENTID 断开原因,或者有时由于 MQTT_KEEP_ALIVE_TIMEOUT 断开原因(MQTT_KEEP_ALIVE_TIMEOUT 每 30-35 分钟发生一次,DUPLICATE_CLIENTID 每 10 分钟发生一次),我得到这个堆栈跟踪
所以,我不明白为什么我需要处理 DUPLICATE_CLIENTID 如果每个客户端都有一个唯一的 ID,并处理 MQTT_KEEP_ALIVE_TIMEOUT 如果没有间歇性连接问题(我每分钟都会收到日志到我的服务器,所以它不是WIFI/互联网问题)。我从这里使用最新的 AWS IoT SDK - https://github.com/aws/aws-iot-device-sdk-java。
我该如何解决这些问题?
我的棘手解决方案:
我添加了一个预定线程,该线程将空消息发送到主题 - ${iot:Connection.Thing.ThingName}/ping 每 20 分钟:
scheduledExecutor.scheduleAtFixedRate(() -> {
try {
iotClient.publish(String.format(Configuration.PING_TOPIC, deviceId), AWSIotQos.QOS0, "");
} catch (AWSIotException e) {
LOGGER.error("Failed to send ping", e);
}
}, Configuration.PING_INITIAL_DELAY_IN_MINUTES, Configuration.PING_PERIOD_IN_MINUTES, TimeUnit.MINUTES);
所以这个解决方案解决了非活动问题,但我仍然想找到一个更优雅的解决方案......
解决方案
查看您的日志,似乎连接丢失,然后重试连接。
在重新连接期间,它仍然使用您传递的 deviceID 进行连接(但是连接可能从 MQTT 端不存在),因此它看到它正在尝试使用相同的 id 进行连接。
阅读一些关于此的内容,看起来您可能实际上并未将您的设备注册为 aws 中的(事物)。
如果你是,当你创建一个 MQTT 连接并传递那个 thingId 时,即使在重新连接时,它也不会给你那个 DuplicateID 错误。
AWSIotMqttClient client = new AWSIotMqttClient(...);
SomeDevice someDevice = new SomeDevice(thingName); // SomeDevice extends AWSIotDevice
client.attach(someDevice);
client.connect();
您也可以尝试一下iotClient.cleanSession(true/false)
,看看是否可以帮助您。
/** * 设置客户端和服务器是否应该在每个连接上建立一个干净的会话。* 如果为 false,则服务器应尝试在连接之间保持客户端的状态。* 这必须在调用 {@link #connect()} 之前设置。* * @param cleanSession * 如果为真,服务器会在每个连接上与客户端启动一个干净的会话。* 如果为 false,则服务器应在连接之间保持客户端的状态。*/
@Override
public void setCleanSession(boolean cleanSession) { super.setCleanSession(cleanSession); }
https://docs.aws.amazon.com/iot/latest/developerguide/iot-thing-management.html
MQTT_KEEP_ALIVE_TIMEOUT 如果在客户端保持活动时间的 1.5 倍内没有客户端-服务器通信,则客户端断开连接。
这意味着你没有发送/接收消息..没有办法解决这个问题,除非你保持活跃的连接并做事
推荐阅读
- data-analysis - 如果年龄变量的数据类型是对象,我想将其转换为数值。但我的模型中出现这样的错误
- flutter - 颤振地理位置没有显示任何内容
- python - 进行类继承时使用 super().__init__() 的问题
- javascript - JavaScript 显示隐藏的输入
- android - 有没有办法在横向或纵向模式下“冻结”应用程序?
- php - woocommerce_quantity_input 出现两次
- java - 无法在 Android 中设置 @react-native-firebase/messaging
- scala - 找出类型构造函数的类型参数,知道它扩展的类型构造函数的类型参数
- asp.net-core - 是否可以在 Windows 8.1 上以 Kestrel 模式运行 Blazor 客户端?
- r - 组内的新变量,每个观察值的总和