You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure IoT Edge自定义模块无法连接Hub,Communication_Error故障求助

Azure IoT Edge自定义模块持续连接中断排查与解决方案

问题描述

自定义IoT Edge模块此前运行正常,近期出现持续连接中断:ConnectionStatusChangeHandler报告状态为ConnectionStatus.Disconnected,原因包含ConnectionStatusChangeReason.Retry_Expired和ConnectionStatusChangeReason.Communication_Error。按最佳实践触发客户端重新初始化后仍无法恢复,无间歇性成功连接,排除临时故障。

检查EdgeHub模块孪生的reported properties,发现clients节点仅列出正常连接的IoTEdgeMetricsCollector模块,自定义模块未被识别:

}, "clients": { 
  "$lastUpdated": "2024-05-22T06:41:40.9107753Z", 
  "deviceId/IoTEdgeMetricsCollector": { 
    "$lastUpdated": "2024-05-22T06:41:40.9107753Z", 
    "status": { "$lastUpdated": "2024-05-22T06:41:40.9107753Z" }, 
    "lastConnectedTimeUtc": { "$lastUpdated": "2024-05-22T06:41:40.9107753Z" } 
  } 
}

自定义模块可正常部署启动,但无法连接EdgeHub发送遥测,模块内捕获WebSocket异常:

HasStack="True" ThreadID="6,006" ProcessorNumber="0" thisOrContextObject="ErrorDelegatingHandler#34683734" memberName="ExecuteWithErrorHandlingAsync" message="Exception caught: System.Net.WebSockets.WebSocketException (0x80004005): Unable to connect to the remote server ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.IO.IOException:  Received an unexpected EOF or 0 bytes from the transport stream. at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter) at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm) at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request) at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.WebSockets.WebSocketHandle.ConnectAsync(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options) at System.Net.WebSockets.WebSocketHandle.ConnectAsync(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options) at System.Net.WebSockets.ClientWebSocket.ConnectAsyncCore(Uri uri, CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.AmqpIot.AmqpIotTransport.CreateClientWebSocketAsync(Uri websocketUri, CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.AmqpIot.AmqpIotTransport.CreateClientWebSocketTransportAsync(CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.AmqpIot.AmqpIotTransport.InitializeAsync(CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.Amqp.AmqpIotConnector.OpenConnectionAsync(CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.Amqp.AmqpConnectionHolder.EnsureConnectionAsync(CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.Amqp.AmqpConnectionHolder.OpenSessionAsync(IDeviceIdentity deviceIdentity, CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.AmqpIot.AmqpUnit.EnsureSessionIsOpenAsync(CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.AmqpIot.AmqpUnit.OpenAsync(CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.Amqp.AmqpTransportHandler.OpenAsync(CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.ProtocolRoutingDelegatingHandler.OpenAsync(CancellationToken cancellationToken) at Microsoft.Azure.Devices.Client.Transport.ErrorDelegatingHandler.<>c__DisplayClass27_0.<ExecuteWithErrorHandlingAsync>b__0>d.MoveNext() --- End of stack trace from previous location --- at Microsoft.Azure.Devices.Client.Transport.ErrorDelegatingHandler.ExecuteWithErrorHandlingAsync[T](Func`1 asyncOperation)"

环境信息

  • 主机:Debian 11,Arm64
  • aziot-edged:1.4.27
  • Edge Agent:1.4.35
  • Edge Hub:1.4.35
  • Docker/Moby:24.0.9-1

已尝试操作

  1. 在Azure门户及分层部署中移除并重新添加自定义模块
  2. 重启网关、系统模块,执行iotedge system restart
  3. 部署SimulatedTemperatureSensor模块,可正常注册到EdgeHub并运行
  4. iotedge check返回全绿,仅少量版本警告
  5. 重启后EdgeHub和EdgeAgent日志无报错

解决方案建议

1. 重置EdgeHub模块孪生配置

推测因意外修改EdgeHub孪生导致模块识别异常,可通过Azure CLI重置EdgeHub的期望属性为默认值:

az iot hub module-twin update --hub-name <你的IoT Hub名称> --device-id <Edge设备ID> --module-name edgeHub --set properties.desired='{}'

执行后等待部署生效,再重新部署自定义模块。

2. 验证自定义模块的连接字符串与SSL证书

  • 检查自定义模块的环境变量EdgeHubConnectionString是否正确,确保使用模块孪生生成的连接字符串
  • 验证设备本地IoT Edge根证书有效性:
    ls /etc/aziot/certs/
    openssl x509 -in /etc/aziot/certs/iotedge-device-ca.crt -text -noout
    
    若证书过期或损坏,重新生成证书:
    sudo iotedge certgen renew
    

3. 检查EdgeHub的端口与网络配置

  • 执行docker inspect edgeHub查看Ports字段,确认默认端口(5671、8883、443)映射正常
  • 检查主机防火墙规则,确保自定义模块可访问EdgeHub端口:
    sudo ufw status
    sudo iptables -L -n
    

4. 清理EdgeHub本地状态缓存

EdgeHub本地缓存可能存在异常,清理后重启:

sudo docker stop edgeHub
sudo docker rm edgeHub
sudo rm -rf /var/lib/aziot/edged/mnt/data/edgeHub
sudo iotedge system restart

5. 切换自定义模块的传输协议

当前AMQP over WebSocket连接失败,可尝试切换为MQTT协议,修改模块代码中的客户端初始化逻辑:

var options = new ClientOptions
{
    TransportSettings = new List<ITransportSettings>
    {
        new MqttTransportSettings(MqttTransportType.Tcp)
    }
};
var deviceClient = DeviceClient.CreateFromConnectionString(connectionString, options);

内容的提问来源于stack exchange,提问作者user1483086

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:20:01