AWS JAVA IoT 客户端重新连接和超时

Posted

技术标签:

【中文标题】AWS JAVA IoT 客户端重新连接和超时【英文标题】:AWS JAVA IoT client reconnections and timeouts 【发布时间】:2021-03-29 02:55:46 【问题描述】:

我在 CONNECTED/DISCONNECTED 主题上使用 IoT 规则(来自 here)。所以我想在设备连接或断开连接时收到电子邮件。在我的设备上,我在启动时运行下一个代码(仅在启动时):

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 分钟发生一次),我会收到此堆栈跟踪

所以,我不明白如果每个客户端都有唯一的 ID,我为什么需要处理 DUPLICATE_CLIENTID,如果 没有间歇性连接问题,我需要处理 MQTT_KEEP_ALIVE_TIMEOUT strong>(我每分钟都会将日志发送到我的服务器,所以这不是 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);

所以这个解决方案解决了不活跃的问题,但我仍然想找到一个更优雅的解决方案......

【问题讨论】:

【参考方案1】:

查看您的日志,似乎连接丢失,然后重试连接。

在重新连接期间,它仍在使用您传递的 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 * 如果为 true,则服务器在每个连接上与客户端启动一个干净的会话。 * 如果为 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 倍时,客户端断开连接。

这意味着你没有发送/接收消息..没有办法解决这个问题,除非你保持活跃的连接并做一些事情

【讨论】:

那么,如果设备已启动,但未发送/接收消息,那么我会每 30 分钟收到有关连接/断开连接状态的电子邮件吗?看起来很奇怪。如何使用 AWS IoT 解决? @Rougher 这是文档所述...如果没有活动,客户端将断开连接。 但是 iotClient.setKeepAliveInterval(0) 呢?将此值设置为 0 将禁用连接的保持活动功能。在这里阅读:github.com/aws/aws-iot-device-sdk-java/blob/master/… 试试@Rougher。也许0让它永远活着?值得一试。请更新我。我很想知道 如果我将 keep-alive 设置为 0,30 分钟后它会断开连接并且不会重新连接。看起来像这个问题:github.com/aws/aws-iot-device-sdk-js/issues/254

以上是关于AWS JAVA IoT 客户端重新连接和超时的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 AWS IOT 的重新连接代码

java客户端调用webservice时 连接超时知道是网络原因 ,如何重试如果不重试程序就死琐了,

在端口 443 上使用 ALPN 将 M2MQTT 客户端库连接到 AWS IoT 时出现问题

如何设置 AWS Appsync 请求超时限制 || AWSAppSync 客户端未提供回调

Mac在连接网络时,客户端界面提示“网络超时,请检查你的网络设置”。怎么办?

tomcat 的 客户端connectionTimeout 网络连接超时后 是自动重新发连接请求还是停止了?