Node-RED 中的错误处理

在一切正常时,创建能正确工作的流程很容易,但同样需要考虑可能出什么问题。

例如,流程与外部数据库或 API 交互时,对方不再响应请求会怎样?MQTT 节点与消息代理失去连接又会怎样?

任何应用都需要错误处理,才能正确应对这类事件。“处理错误”具体意味着什么,取决于应用要求。你可能希望重试失败的操作、触发单独的告警;也可能这个错误完全在预期之内,只是应用逻辑的一部分。

Node-RED 提供两种方式,让节点报告错误。它可以只向日志写一条消息,也可以将错误通知运行时,从而触发某个流程。

如果错误仅被写入日志,你会在 Debug 侧栏和日志输出中看到消息,但无法创建流程来处理。这类错误是不可捕获的错误。

如果节点正确地通知运行时,该错误便是可捕获的错误,可用于触发错误处理流程。

还有第三类错误,会导致 Node-RED 运行时关闭。这种 uncaughtException 错误无法在流程中处理,是节点中的程序缺陷造成的。

本指南进一步介绍各类错误及其处理方法,也会说明如何利用节点的 Status 事件创建流程,处理意外事件。

记录错误

节点记录错误时,它会出现在 Debug 侧栏中。

Debug 侧栏中的错误消息

Debug 侧栏中的错误消息

官方原图:Debug 侧栏中的错误消息。来源:Node-RED 官方文档

这里显示错误消息、发生日期与时间,以及记录错误的节点。与其他 Debug 消息一样,将鼠标悬停在消息上,会在工作区中高亮对应节点。如果它不在当前视图中,点击消息顶部角落的节点名称,可以在工作区中显示该节点。

可捕获的错误

如果节点将错误通知运行时,可以使用 Catch 节点创建流程来处理。

Catch 节点错误处理流程

Catch 节点

官方原图:Catch 节点错误处理流程。来源:Node-RED 官方文档

如果错误被 Catch 节点捕获,就不会记录到 Debug 侧栏。

Catch 发出的消息,是报告错误的节点提供的消息。它会设置一个 error 属性,包含错误信息:

{
    "topic": ...,
    "payload": ...,
    "error": {
        "message": "An error",
        "source": {
            "id": "2e25823d.fa3f7e",
            "type": "function",
            "name": "My Function",
            "count": 1
        }
    }
}

msg.error 的属性如下:

  • msg.error:
    • message:错误消息
    • source:记录错误的节点信息:
      • id:源节点 ID
      • type:源节点类型
      • name:源节点设置的名称(如果有)
      • count:该消息被该节点抛出的次数。运行时通过此属性检测卡在循环中的消息:消息传回源节点,节点再次记录错误,再传回,以此类推。运行时允许消息循环 9 次,此后记录一个不可捕获的错误,打破循环。删除这个属性就会禁用此检查。

如果节点报告错误时,消息已经有 msg.error 属性,原有属性会被移到 msg._error。

默认情况下,Catch 节点会被编辑器同一标签页中的所有节点触发,也可以配置为只监视该标签页中的指定节点。

如果同一标签页有两个 Catch 节点,而且都监视同一个节点,那么该节点报告的任何错误,都会触发这两个 Catch 节点。

当 Catch 节点被配置为监视所有节点时,还可以设置为仅在错误尚未被另一个 Catch 节点捕获时触发。这样就能为特定节点创建错误处理流程,同时再创建一个负责捕获“其余所有错误”的处理器。

子流程中的错误

如果错误来自子流程内部,运行时会先检查子流程里是否有 Catch 节点。如果没有,错误会向上传播到包含该子流程实例的流程。

不可捕获的错误

这类错误由节点写入日志,但没有正确通知运行时,不能用 Catch 节点处理。

节点可能提供替代处理方式。例如,更新它的状态属性,由 Status 节点监视;也可能正常发送消息,但设置额外属性来表示错误。

你可以联系节点作者,询问是否能更新节点,以正确报告错误。

uncaughtException 错误

这是一类特殊的 Node.js 错误,发生在节点没有正确处理内部错误时。它会使整个 Node-RED 运行时关闭,因为这是唯一安全的做法。

这听起来可能很极端,但 Node.js 文档用下面的类比解释了风险:

未捕获异常之后尝试正常恢复运行,就像升级电脑时突然拔掉电源线:十次里面可能九次看似没有出事,第十次却可能损坏系统。

典型原因是节点启动了一个异步任务,而该任务发生错误。编写完善的节点会为任务注册错误处理器;如果没有,错误就无法被捕获。

遇到这类错误时,应尝试找出导致错误的节点,并向它提交问题。由于错误涉及异步执行,这不总是容易。

Node-RED 日志中的堆栈跟踪,可以提供发生错误的异步任务的线索,进而帮助识别出错节点。

处理状态变化

并非所有异常状态都会产生可由 Catch 节点捕获的错误事件。例如,MQTT 节点断开连接时,不会触发错误,却会触发状态变化。

正如 Catch 节点可以处理错误事件,Status 节点可以处理节点状态变化。

Status 节点发出的消息包含 status 属性,提供状态信息及触发事件的节点信息:

{
    "status": {
        "fill": "red",
        "shape": "ring",
        "text": "node-red:common.status.disconnected",
        "source": {
            "id": "27bbb5b1.d3eb3a",
            "type": "mqtt out"
        }
    }
}

原文:Handling errors,OpenJS Foundation and Node-RED contributors。本页为中文翻译,代码示例保留原文;Node.js 引文译述了原文中的风险类比。

Copyright OpenJS Foundation and Node-RED contributors. All rights reserved.

Copyright 2016 JS Foundation and other contributors, https://js.foundation/
Copyright 2013, 2016 IBM Corp.

文档仓库采用 Apache License 2.0,见仓库许可声明。材料按现状提供,不附带明示或默示担保。原图来自 Node-RED 官方文档。商标及品牌的权利归各自持有人;参见 OpenJS Foundation 的商标政策和商标列表。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容