node.js服务器端-处理错误。 第一部分

下午好

本文针对的是熟悉node.js的开发人员。

最近,我正在准备有关事实的资料,这些资料对于我们办公室中的node.js的开发人员而言非常有用。 我们正在研究的项目是使用node.js express模块​​作为Web服务器的API服务。 该材料基于实际情况,在这些情况下,代码无法正常工作或代码中的逻辑被仔细隐藏,或者在扩展过程中引发错误。 在此材料的基础上,举办了员工发展研讨会。

因此,我决定分享。 到目前为止,只有第一部分约为30%。 如果有兴趣,将继续!

我试图提供一个快速熟悉的机会,所以我将示例,推理和评论隐藏在扰流板上。 如果陈述显而易见,则可以跳过“水”。 尽管我们在扰流板上的“耙”也可能很有趣。

研讨会期间的一位同事问我一个问题,为什么要讨论这个问题,如果此文档中已有所有内容。 我的回答如下。 尽管该信息是真实的,但文档中确实包含了所有内容,但我们仍然会犯一些令人讨厌的错误,这些错误与对基本事物的误解或不了解有关。

让我们开始吧!

Node.js虚拟机



单线程



与javavm不同,nodejs-vm是单线程**



来源

更多细节
同时,虚拟机本身会使用一组辅助线程,例如,用于组织I / O。 但是所有用户代码仅在一个“主”线程中执行。

由于没有竞争,因此极大地简化了生活。 代码执行不能在任意位置中断并在另一个位置继续。 只需执行代码即可,直到需要等待某些东西(例如,从文件读取数据准备就绪)为止。 在等待期间,可能会执行另一个处理程序,直到它完成工作或也开始等待某些东西为止。

也就是说,如果存在内部数据结构,则无需担心同步对其的访问!

如果“主”线程没有时间处理数据该怎么办?

通过启动另一个node.js进程或如果服务器资源即将用尽,则通过启动另一个服务器来完成扩展。

后果和我们的“耙子”
这里的一切也很清楚。 您应该始终为可能(并且很可能会)有多个node.js进程这一事实做好准备。 有时也可能有几台服务器。

在我们的代码中找到了被隐藏的“耙”


平行线在无限远处相交。 无法证明,但我明白了。
让·埃菲尔(Jean Effel),“亚当夏娃的小说”。
尝试确保应用程序专门确保数据库中实体实例的唯一性。 通常,这种情况与上下文隔离看起来并不糟糕 ,但在这种情况下甚至更糟。 在没有第三方服务的情况下,此任务对我来说似乎没有解决方案。

从事此工作的同事确实确实希望在不涉及实际数据库的情况下实现这一目标。 最后,经过一些“射弹的解决方案”,它通过与SharePoint的结合实现了。


**多线程或“如果您真的想”



从版本10.5.0开始,node.js 对多线程提供了实验性支持


来源

但是范式保持不变
  • 每个新的工作流程都会创建自己的虚拟机node.js环境隔离实例。
  • 工作流缺少通用的可变数据。 (有一些保留意见,但基本上该声明是公平的。)
  • 使用消息和SharedArrayBuffer完成通信。

因此,使用工作流时,旧代码将继续起作用。
在这里阅读更多。


应用程序生命周期



nodejs-vm的核心是事件循环。 当应该暂停代码执行或代码似乎已经结束时,控制权就交给了它。

隐藏文字
事件循环检查(哦)我们注册处理程序的事件是否发生。 如果发生某些情况,则将调用处理程序。 如果不是,将检查是否有我们注册了处理程序的事件“生成器”。 打开的tcp连接或计时器可以是此类生成器。 如果找不到它们,则程序退出。 否则,将发生这些事件之一,调用处理程序,然后一切重复。

此行为的结果是,当代码似乎结束时,不会发生从nodejs-vm退出的情况,例如,因为我们注册了一个计时器处理程序,应在一段时间后调用它。

在下面的示例中显示。

console.log('registering timer callbacks'); setTimeout( function() { console.log('Timer Event 1'); }, 1000); console.log('Is it the end?'); 


结果:
 registering timer callbacks Is it the end? Timer Event 1 


在这里阅读更多。

我们代码中的另一个“耙”



每个人都可以管理状态!
用户是否是管理员的标志存储在全局变量中。 该变量在程序开始时初始化为false。 稍后,当管理员注册时,此变量设置为true。

结果,如果管理员访问了系统,则访问该服务实例的任何用户都将被视为管理员。

我花了一些力气向同事展示逻辑上有错误。 一位同事确信,对于每个http请求,都会创建一个全新的环境。


package.json-值得填充的字段



package.json是我们软件包的描述文件。 在这种情况下,它与我们的应用程序有关,与依赖性无关。 下面列出的字段和解释说明了为什么都应该全部填写。

隐藏文字


在我们将软件包发布到资源库之前,也可以对字段进行评分。 问题在于,此字段可方便用于命名安装文件或例如在其网页上显示产品名称。 通常来说,“你叫游艇什么..”

版本号


主要思想是不要忘记在扩展功能,修复错误的同时增加版本号,但是...不幸的是,在我们的办公室中,您仍然可以找到版本0.0.0不变的产品。 然后猜猜哪种功能适用于客户端...

主要的


字段告诉我们应用程序启动时将启动哪个文件(`npm start`)。 如果将软件包用作依赖项,那么当另一个应用程序使用我们的模块时,将导入哪个文件。 当前目录是package.json文件所在的目录。

而且,例如,如果我们使用vscode ,则在调用调试器或运行“ execute”命令时,将启动此字段中指定的文件。

扩展名“ .js”可以省略。 而是所有可能的用例的结果,因此在文档中未直接说明。

引擎


该字段包含元组:{“ node”: version ,“ npm”: version ,...}。

我知道字段“节点”和“ npm”。 它们确定了我们的应用程序运行所需的node.js和npm版本。 通过运行npm install命令检查版本。

支持用于确定依赖项软件包版本的标准语法:不带前缀(单个版本),前缀“〜”(版本的前两个数字必须匹配)和前缀“ ^”(仅版本的第一个数字必须匹配)。 如果有前缀,则版本必须大于或等于此字段中指定的版本。 只是版本列表; 明确指示更多,更少,...等。 也可以。

免责声明 仅当启用“引擎限制”模式时,“ Npm install”才检查“引擎”中指定的版本。 我们将其包含在每个项目中,并在行中添加.npmrc文件:“ engine-strict = true”。 以前,“ npm install”默认情况下会执行此检查。

至少在文档中,一些容器写明默认情况下将使用合适的版本。 在这种情况下,我们正在谈论Azure。

一个例子:
 "engines": { "node": "~8.11", // require node version 8.11.* starting from 8.11.0 "npm": "^6.0.1" // require npm version 6.* starting from 6.0.1 }, 


定期的“耙子”



国王是赤裸的!

反复与客户达成共识,要求的“ node.js”版本至少应为8。当应用程序的初始版本交付时,一切正常。 在客户端交付新版本后的“一天”,该应用程序停止运行。 一切在我们的测试中都有效。

问题在于,在此版本中,我们开始使用仅受版本8 node.js支持的功能。 “ engines”字段没有填写,因此没有人注意到客户端具有旧版本的node.js。 (Azure Web服务默认)。

剧本


该字段包含以下格式的元组:{“ script1”: script1 ,“ script2”: script2 ,...}。

有在特定情况下运行的标准脚本。 例如,运行“ npm install”后将执行“安装”脚本。 例如,检查应用程序正常运行所必需的程序的可用性非常方便。 或者说,压缩通过我们的Web服务可用的所有静态文件,这样就不必动态压缩它们。

在这种情况下,您不仅可以局限于标准名称。 为了执行任意脚本,您需要运行“ npm run script-name ”。

将所有使用的脚本收集在一处很方便。

一个例子:
  "scripts": { "install": "node scripts/install-extras", "start": "node src/well/hidden/main/server extra_param_1 extra_param_2", "another-script": "node scripts/another-script" } 


PS在大多数情况下,可以省略扩展名“ .js”。


package-lock.json-帮助安装特定版本的依赖项,而不是“最新”版本



隐藏文字
git还是不git?


该文件相对较新出现在npm中。 其目的是组织组件的可重复性。

还有一个“耙子”


但是我没有更改程序中的任何内容! 昨天她工作了!


在对等机器上,该应用程序运行良好。 在相同环境中的另一台计算机上,从git到新目录的应用程序中,执行“ npm install”后,“ npm start”出现了前所未有的错误。

该问题是由于git存储库中缺少文件“ package-lock.json”而引起的。 因此,在安装软件包的过程中,应尽可能新鲜地安装第二个或更多个级别的所有依赖项(自然地,不是写在package.json中)。 在同事的计算机上,一切都很好。 在测试的计算机上选择了一组不兼容的版本。

package-lock.json-git!



从题外话回来。 文件“ package-lock.json”包含为我们的应用程序本地安装的所有模块的列表。 该文件的存在使您可以重新创建一对一的模块版本集。

简介:不要忘了将git放入应用程序的交付(安装)文件中!

有用:如果缺少文件“ package-lock.json”,但是目录“ node_modules”包含所有必需的模块,则可以重新创建文件“ package-lock.json”:
 npm shrinkwrap rename npm-shrinkwrap.json package-lock.json 



您现在可以结束此操作。 未包括的信息是我们团队使用的代码简化技术。

如果检测到错误,我将尝试快速修复它们!

Source: https://habr.com/ru/post/zh-CN430972/


All Articles