用例- #unpublish Happens -如何保护你的Node.js投资

文摘:

Igor Soarez /首席工程师/ YLD, 2016年5月:说到底,npm是一个注册表,它是一个与Node.js捆绑在一起的工具。但它也有一定的权衡。
依赖npm进行构建和部署的权衡是什么?我们如何处理这个问题?最好的指导方针是什么?
您不能依赖社区来支持您的业务,开源开发人员不能为您的公司工作,您不能在公共包存储库上支持您的生产环境。
你需要检查安全。您需要确保部署到生产环境中的版本始终一致。因为注册表是一个外部依赖项,所以需要降低这种风险。解决方案不能由不提供SLA的第三方维护——您需要能够依赖于用于部署的任何工具。我们的目标是提出一个解决这个问题的体系结构。

讨论转录:

我是伊戈尔。我在Node工作四年多了。我帮助各种各样的公司,从初创公司到企业采用Node。构建框架,微服务,基本的web开发,所有的工作。

我为YLD工作。YLD是一家总部设在伦敦的咨询公司。我们已经做了两年半了。YLD是由Nodejitsu的创建者创立的。Nodejitsu是Node应用程序的参考平台服务。现在他们已经被收购了。那时,是Nodejitsu和YLD的创始人在运行公共NPM注册表。我们是Node基金会的创始成员。这是覆盖Node.js项目的基础。

我们在这个行业中交付软件的方式一直在改变。我们将这些变化视为工程的未来。比尔·斯科特是我们公司的顾问,他在PayPal做了这些改变。这就是把工作分成小的、有才能的、独立的团队。还要时刻关注客户的价值。我们认为Node是促进这种变化的一个很好的工具。

Node社区已经走过了漫长的道路。它发展得非常快,从许多方面来看,Node是目前发展最快、最重要的开发语言。它有400万用户,我们看到它的增长是每年的两倍。特别是在企业中,自去年以来,采用率上升了400%。节点无处不在。

不久之前,Node只是Ryan Dahl的一个副项目。这张图片来自Ryan介绍Node作为JSConf Europe的视频。这个聪明的人把JavaScript(一种没有任何I/O的语言)和Livy VC(一个同步I/O库)放在一起,把JavaScript带到服务器上。他想要一个事件驱动的、非阻塞的I/O。他使Node轻量级且高性能,即使在极端负载下也是如此。这是不久前的事。

如今,很多企业都在使用它。但在很多方面,Node仍然被认为是不成熟的,经常被认为是不成熟的。尤其是老年人——其他老年人社区。我认为一个重要的原因是JavaScript是一种流行的语言。这是RedMonk的编程语言排名。他们是总部位于伦敦的领先行业分析公司。JavaScript实际上是最流行的语言。

它开始于浏览器,但现在你可以在任何地方运行JavaScript。Node社区的很大一部分是由web开发人员组成的。Node使用JavaScript,浏览器运行JavaScript,但JavaScript和服务器并不等同于JavaScript和客户端。而且这些web开发人员通常没有任何工程背景。我们相信工程师和开发人员之间是有区别的。由于对工程的高度关注,我们YLD希望考虑我们选择的工具集的所有方面,从安全性到构建管道。在社会上,这一点总是没有得到足够的重视。

Node降低了新后端开发人员的进入门槛,这一点很好。但它也解释了为什么社区有时似乎有点脱离既定的工程实践。这是我们在YLD非常努力地帮助客户的事情。

但Node不断被采用,企业使用仍在增长,这是有充分理由的。Node是一个简单、强大且灵活的工具。它在不影响性能的情况下简化了I/O。但重要的是要记住,并非所有用例都适合Node。[…]确保您的组织采用Node是为了正确的用例。

我们经常在企业中发现的Node的最佳用例之一是我们喜欢称之为专用后端的东西。或者也通常被称为前端的后端。Node很好地为应用程序开发人员在服务器端提供了一块土地。我的意思是,它使应用程序或客户团队能够灵活地为他们所瞄准的平台构建所需的支持,而不必不断地与API或后端团队来回奔波。因此,它创造了灵活性和速度,并允许您更快地向客户交付价值。所有这些都不会影响安全性或性能。但这并不意味着采用Node就没有风险。

我们还没有找到一个没有依赖关系的企业Node.js项目。Node拥有一个充满活力的社区。它有一个非常丰富的公共包生态系统,自然你想要最大限度地利用它。在Node中,开发文化提倡将问题分解为许多小模块,这些模块只做一件事,并且做好一件事。因此,与其他技术相比,Node项目平均上会有更多的依赖项。这是Node最大的优势之一,但也可能是它的弱点之一——如果你不小心的话,这就是它的弱点之一。

因此,处理越来越多的依赖性可能是一种斗争。这就是强大的工程实践可以保护你和你的投资的地方。

所有这些公共包都在NPM上共享。NPM是一个公共注册中心。任何人都可以发布,而且它是免费使用的。NPM是Node的官方包管理器。它也是公共登记处。这也是一个初创公司。NPM客户端与Node绑定在一起。当你安装Node时,你会得到NPM。但是,虽然Node是在一个由对其有投资兴趣的公司组成的基金会下管理的,但公共NPM注册中心是由一家名为NPM Inc.的私人公司运行和管理的。因此,每个做Node的人共享他们工作的公共注册中心是由一家私人公司控制的。 It’s not under the control of the foundation.

当你安装Node时,你会得到NPM和一个默认使用或指向NPM Inc.运行的公共注册中心的NPM配置。如果由于某种原因,公共NPM注册表不可用,这可能会中断整个团队的开发。如果您试图在公共注册表不可用的情况下安装旧模块,就会看到这种情况。在这个实例中,我们试图安装joi包。但你得到的不是快乐,而是沮丧。

由于各种各样的原因,公共登记处可能而且已经关闭了。即使它没有下降,它也会很慢。您最不希望看到的就是您的团队经常无所事事地等待免费和公共注册表。

比开发更糟糕的是构建和部署。每次构建被触发时,您都需要运行NPM install。如果NPM安装失败,整个构建就会失败。这将延迟发布周期。如果在部署时运行NPM install,结果可能会更糟。在部署期间减少容量的持续部署和或集成管道可能会给可用的生产实例带来不必要的压力。

记住,如果你在使用NPM,可怕的事实是你在依赖陌生人。你正在使用他们的软件包。使用公共注册中心可以让您受任意数量的包作者的支配。最近NPM因为破坏网络而上了媒体的头条。像WordPress。com这样的网站受到了影响。这个开发人员决定删除这个小包,因为它是数百个其他包的依赖,并破坏了数千个项目。这次事件发生后,公共登记处现在禁止删除已发布的软件包。但是,开源贡献仍然可以通过许多方式影响您的项目。

如果您考虑安全性,那么您只需要一个坏模块。同样,节点的方式是有许多小的依赖,它们只做一件事,一件事做得很好。但是平均而言,Node模块的特定版本出现安全问题的可能性是0.5%。那么一个有30个依赖项的项目,就有15%的几率支持一个安全漏洞。这非常可怕。即使它不是一个安全更新,即使它不是一个安全问题,如果它只是一个bug或不兼容的更新,那就已经足够糟糕了。因为有这么多依赖项,所以您不希望被困在特定的版本上,而不得不手动更新每一个版本。但是由于每天都有这么多对公共NPM包的更新,很有可能从你测试和部署它的时候开始,你就会得到不同的软件。更好的运行和更快的软件是很好的,但这也可能是破坏性的更改或bug。不可预测的变化是不可接受的风险。

在旧项目中,依赖项是用范围指定的。有很多方法可以指定这些范围。您可以参考一个特定的版本。您可以允许高于某个版本的任何版本。如果使用波浪线,则允许新的补丁。如果使用插入符号,也允许新的小调版本,但不允许大调版本,有不同的方法。指南和默认的指定方法一直有很多争议,它已经改变了很多次。

NPM建议使用semver进行应用程序版本控制。这是一组试图将兼容的更改从不兼容的更改中分离出来的规则。但实际情况是,完全取决于包作者是否遵守这一规则。如果您所依赖的包永远不跟随,这可能会产生问题。或者—并且包的新版本有突破性的更改。而且,即使包的作者遵循semver,仍然有可能在兼容版本中引入bug。

选择依赖项已经足够困难了。这些都是你需要考虑的。比如许可、发布频率、作者是否响应开放问题、测试覆盖率等等。随着依赖性的增加,这加剧了这个问题。

如果你看到了所有这些问题,你能做些什么呢?这里的教训是什么?第一条也是最重要的一条规则是,在部署时不要运行NPM install。我们看到这种情况的次数是惊人的。如果注册表不可用,或者由于其他原因NPM安装失败,那么当你需要它们时,你可能没有足够的供应服务器。相反,您应该尝试部署预构建的工件。

您还需要掌握您所依赖的软件。即使在构建这些工件时,您也不希望为此依赖公共注册中心。

所以解决方案是保留一个缓存,在你的控制下保留每个依赖项的副本。过去,Node社区的一个建议是,应用程序应该将它们的依赖项检查到源代码控制中。本质上是将依赖捆绑或出售到应用程序中。

但这可能会非常混乱。因为有了原生模块,NPM包中包含了C和c++代码和makefiles,而不仅仅是JavaScript。在安装它们时,需要对它们进行编译。这将针对开发人员机器与开发人员机器之间不同的特定架构。这与你所瞄准的环境不同。每次签出项目时,你只做NPM重建,你需要对签入源代码控制的文件有选择性。这可能是一场噩梦。更不用说差异会让人读起来不舒服。而整个版本控制系统将变成一个棘手的问题。

更好的解决方案是使用私有包存储库。到公共注册中心的缓存代理。每次添加新的依赖项时,都将其持久地缓存在您的控制之下。Artifactory是我们大多数客户使用的产品。它支持NPM,您可以将它配置为公共注册中心的缓存代理。一旦你开始使用你的依赖项,它就会被缓存,如果NPM不可用,如果一个包被拉出,如果任何麻烦来了,你是安全的。您拥有继续开发、构建和部署所需的资源。它还允许您将公共包发布到您自己的私有包存储库中。这是不错的。

设置起来真的很简单。您所需要做的就是配置NPM。更改此配置文件并为注册表设置不同的端点。我想做一个演示,但我觉得在飞机上做会更酷。

所以我用手机拍了下来。我的笔记本电脑连不上。我在hapi项目,这是一个流行的网络开发框架节点。我删除了所有的依赖项。检查注册中心的npm配置。我们将看到它指向在Docker上本地运行的Artifactory。然后我们运行NPM install,即使公共注册表不可用(因为所有模块都缓存在Artifactory下),您仍然能够安装。

这就解决了可用性问题。但是更新呢?在切割和测试之间[…]会对你的依赖进行更新。即使您不使用版本范围,即使您将项目依赖关系指定为特定的版本,这也只能解决直接依赖关系的问题。它不能解决暂时依赖的问题。

解决这个问题的一个方法是使用NPM塑料薄膜。如果你在你的项目上运行npm shrinkwrap,它会创建一个文件,列出当前安装的所有npm模块的名称和特定版本。你应该检入版本控制的这个文件将被NPM和NPM安装引用。当NPM install再次运行时,它实际上会忽略依赖规范和包json,而是安装这些特定的版本。

由Mozilla创建的模块NPM -lock甚至不仅会列出名称和版本,还会保存校验和,并在再次运行NPM install时验证它们。因此,即使一个特定的版本被覆盖,如果有任何变化,npm将会严重失败,你会知道包已经发生了变化。

如果您正在构建容器,那就更简单了,这些都不是问题。如果构建系统的结果是一个映像,那么所有依赖项都捆绑在该工件中。而且这个工件可以从一个环境传递到另一个环境,而没有任何这些变化的问题。

但如果所有东西都被冻结了,如果你锁定了所有依赖项,你怎么得到新软件呢?如何管理依赖项的更新?运行过时的NPM可以帮助你跟踪过时的依赖项。它告诉你你落后了多少。

黄色的包表示该模块有一个新版本,但您的依赖规范不允许升级。红色,不确定你能不能看到但中间的ejs是红色的,意味着你应该再次运行NPM install,这样你就能得到一个模块的新兼容版本。

为了尽量减少安全问题的意外,在构建管道上运行snky是一个非常好的主意。Snky是一个免费的开发工具,它根据名称和版本收集您的依赖项,并对公共漏洞数据库进行查询。所以它会警告你依赖的安全问题,让你知道升级或降级到一个更安全的版本,或者完全摆脱那个依赖。

我们也一直在研究一个很酷的工具。所谓的披露。我现在想给你们展示一下。好的。

因此,如果你在一个项目上运行披露,它也会查看你的依赖列表,并尝试给你一个概述,如果它工作。我有网络吗?好的。

所以我在hapi项目上运行这个,它列出了所有的依赖项以及您接触到的许可。它让您大致了解这些依赖项的可靠性。它试图查看代码行数,是否有统计信息,包或版本是否已弃用或过时。我们想让它看看其他指标,比如GitHub上的开放问题的数量,以及它们被关闭的频率。更新源的频率。它还会告诉你,委托给snky。它会告诉你是否有任何安全问题,并试图给你的依赖项评分。我想还有一个例子。表达。

我们想把它变成开源的。我现在就来做。好了。所以我们期待人们使用它并获得贡献。好吧。

总而言之,不要在部署时运行NPM install,保留所有依赖项的副本,了解你要接触的是什么,你可以使用公开,运行漏洞扫描,并尝试缩小依赖项的版本。这是所有。谢谢你!

快速释放,否则死亡