如何解决:Node.js 服务器中的 onclosenexttick 过早关闭?
How to solve: premature close at onclosenexttick in Node.js Server?
如何解决这个错误,我 运行 我的 Node.js 使用 AWS IoT 然后它有时会显示这个错误:
throw er; // Unhandled 'error' event
^
Error: How (/home/ec2-user/work/nodejs_27_01/node_modules/end-of-stream/index.js:54: 86)
at processTicksAndRejections (internal/process/task_queues.js:79:11)
Emitted 'error' event on DeviceClient instance at:
at MqttClient.<anonymous> (/home/ec2-user/work/nodejs_27_01/node_modules/aws-iot-device-sdk/ device/index.js:772:15)
at MqttClient.emit (events.js:333:22)
at MqttClient.EventEmitter.emit (domain.js:485:12)
at TLSSocket.f (/home/ec2-user/work/nodejs_27_01/node_modules/once/once.js:25:25)
at onclosenexttick (/home/ec2-user/work/nodejs_27_01/node_modules/end-of-stream/index.js:54: 73)
这可能有多种原因:
具有相同 ClientId 的多个连接
clientId 一次只能用于一个连接。如果您在建立另一个连接时使用相同的 clientId 连接,旧连接将被丢弃(这会导致过早关闭错误)并建立新连接。
The client is using a client ID that is already in use. In this case, the client that is already connected will be disconnected [...]. (Source)
权限
如果设备(来自 aws-iot-device-sdk-js 的 mqtt.Client)没有正确的权限来连接给定主题的 and/or publish/subscribe/receive 消息,就会发生此错误。
查看此处了解更多文档:https://docs.aws.amazon.com/iot/latest/developerguide/pub-sub-policy.html
策略应如下所示(示例显示 Cloudformation Iot Policy 资源):
MyIotThingsPolicy:
Type: AWS::IoT::Policy
Properties:
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action: iot:Connect
Effect: Allow
Resource: !Join [ "", [!Sub "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:client/",
"${iot:ClientId}"] ]
- Action: iot:Receive
Effect: Allow
Resource: !Join [ "", [!Sub "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/",
"${iot:ClientId}/eg/your/broadcast/topic"] ]
- Action: iot:Subscribe
Effect: Allow
Resource: !Join [ "", [!Sub "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topicfilter/",
"${iot:ClientId}/eg/your/broadcast/topic"] ]
- Action: iot:Publish
Effect: Allow
Resource: !Join [ "", [!Sub "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/",
"${iot:ClientId}/eg/your/publish/topic"] ]
!Join
是必需的,因为 Cloudformation 会尝试解析 ${iot:ClientId}
,这是一个运行时值,在部署期间未知。
疑难解答
正如Sandeep Patel也建议的那样,如果你想在客户端处理这种情况,你应该实现一个错误回调:
device.on('error', (error) => {
// error.message might be 'premature close'
});
您还可以在主题 $aws/events/presence/disconnected/<clientId>
上查找 disconnectReason
,请参阅:https://docs.aws.amazon.com/iot/latest/developerguide/life-cycle-events.html
我可以不受任何限制地使用该策略解决这个问题,它适用于 me.Since 我不想限制连接的客户端以及订阅或发布的主题我使用了这个策略
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:*",
"Resource": "*"
}
]
在测试时,我附加了具有完整 "Action": "iot:*"
权限的策略,但未能激活 新创建的证书。请转到 IoT 核心服务,Secure
-->
Certificates
并确认附加到 <Thing>
的证书已激活,如果您确认连接到 error Error: premature close
终点为:
telnet <your-iot-endpoint> 8883
.
请参阅附件图片,了解上述指定页面上每个证书可用的选项。
如何解决这个错误,我 运行 我的 Node.js 使用 AWS IoT 然后它有时会显示这个错误:
throw er; // Unhandled 'error' event
^
Error: How (/home/ec2-user/work/nodejs_27_01/node_modules/end-of-stream/index.js:54: 86)
at processTicksAndRejections (internal/process/task_queues.js:79:11)
Emitted 'error' event on DeviceClient instance at:
at MqttClient.<anonymous> (/home/ec2-user/work/nodejs_27_01/node_modules/aws-iot-device-sdk/ device/index.js:772:15)
at MqttClient.emit (events.js:333:22)
at MqttClient.EventEmitter.emit (domain.js:485:12)
at TLSSocket.f (/home/ec2-user/work/nodejs_27_01/node_modules/once/once.js:25:25)
at onclosenexttick (/home/ec2-user/work/nodejs_27_01/node_modules/end-of-stream/index.js:54: 73)
这可能有多种原因:
具有相同 ClientId 的多个连接
clientId 一次只能用于一个连接。如果您在建立另一个连接时使用相同的 clientId 连接,旧连接将被丢弃(这会导致过早关闭错误)并建立新连接。
The client is using a client ID that is already in use. In this case, the client that is already connected will be disconnected [...]. (Source)
权限
如果设备(来自 aws-iot-device-sdk-js 的 mqtt.Client)没有正确的权限来连接给定主题的 and/or publish/subscribe/receive 消息,就会发生此错误。
查看此处了解更多文档:https://docs.aws.amazon.com/iot/latest/developerguide/pub-sub-policy.html
策略应如下所示(示例显示 Cloudformation Iot Policy 资源):
MyIotThingsPolicy:
Type: AWS::IoT::Policy
Properties:
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action: iot:Connect
Effect: Allow
Resource: !Join [ "", [!Sub "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:client/",
"${iot:ClientId}"] ]
- Action: iot:Receive
Effect: Allow
Resource: !Join [ "", [!Sub "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/",
"${iot:ClientId}/eg/your/broadcast/topic"] ]
- Action: iot:Subscribe
Effect: Allow
Resource: !Join [ "", [!Sub "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topicfilter/",
"${iot:ClientId}/eg/your/broadcast/topic"] ]
- Action: iot:Publish
Effect: Allow
Resource: !Join [ "", [!Sub "arn:aws:iot:${AWS::Region}:${AWS::AccountId}:topic/",
"${iot:ClientId}/eg/your/publish/topic"] ]
!Join
是必需的,因为 Cloudformation 会尝试解析 ${iot:ClientId}
,这是一个运行时值,在部署期间未知。
疑难解答
正如Sandeep Patel也建议的那样,如果你想在客户端处理这种情况,你应该实现一个错误回调:
device.on('error', (error) => { // error.message might be 'premature close' });
您还可以在主题
$aws/events/presence/disconnected/<clientId>
上查找disconnectReason
,请参阅:https://docs.aws.amazon.com/iot/latest/developerguide/life-cycle-events.html
我可以不受任何限制地使用该策略解决这个问题,它适用于 me.Since 我不想限制连接的客户端以及订阅或发布的主题我使用了这个策略
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:*",
"Resource": "*"
}
]
在测试时,我附加了具有完整 "Action": "iot:*"
权限的策略,但未能激活 新创建的证书。请转到 IoT 核心服务,Secure
-->
Certificates
并确认附加到 <Thing>
的证书已激活,如果您确认连接到 error Error: premature close
终点为:
telnet <your-iot-endpoint> 8883
.
请参阅附件图片,了解上述指定页面上每个证书可用的选项。