头图
本文是 2021 年 12 月 26 日,第三十五届 - 前端早早聊【前端搞 Node.js】专场,来自阿里巴巴的终端高级技术专家 —— 秦粤的分享。感谢 AI 的发展,借助 GPT 的能力,最近我们终于可以非常高效地将各位讲师的精彩分享文本化后,分享给大家。(完整版含演示请看录播视频):https://www.zaozao.run/video/c35

完整 PPT 请联系小助手(vx:zzleva)获取

正文如下

大家好,今天给大家分享的主题是《浮华过后的 Node.js》。我先简单介绍一下自己:我是极客时间《Serverless 入门课》专栏讲师,同时,我担任阿里巴巴前端委员会-标准化方向的负责人,参与低代码和 Node.js 方向的共建,也是阿里设计效率中台 D-One 的负责人,并且还是 W3C、ECMA-TC39、JSCIG 的成员。

前言

大家可以看到,我所从事的工作范围非常广泛,准确来说,我是一名全栈工程师。但现在,我开始转向管理方向。因为我不确定大家的认知基础如何,所以在介绍今天的内容之前,我会先分享一些共识,以确保大家都能理解。

第一,我想分享的是关于 Node.js 在服务端运行的场景。此部分内容将不涉及 Node.js 用于 CLI 工具或开发端工具的方面。

第二,我想讨论的是企业级应用的定义。企业级应用通常是指为大型企业或商业组织创建和部署的解决方案和应用。在设计企业级应用时,需要考虑到可能访问的 PV/UV 比较大、事务密集、数据量大、用户多以及安全性等方面。

第三,我想分享的是邓宁-克鲁格效应,它是人类学习新事物或认知新事物时的一种认知偏见,分为五个阶段:

  • 第一个阶段是一无所知
  • 第二个阶段是愚民之峰
  • 第三个阶段是绝望之谷
  • 第四个阶段是启蒙爬坡
  • 第五个阶段是持续平原

人在认知一个新的事物或学习过程中,通常都会经历一个类似曲线的过程。比如,当你开始学习 Node.js 时,刚开始的时候你对它会有很高的期望,但实际情况可能与你的预期相差很大,可能会发现有些东西 Node.js 做不了,或者需要很复杂的操作。这时候可能会感到一种低谷,但是随着不断的学习和投入,你会出现一个比较高速的爬升过程,也就是启蒙爬坡。当你掌握 Node.js 的能力越来越熟练时,如果想要将其应用于生产环境中,你会发现这中间还存在很大的跨度,这时候需要花费很长时间才能缓慢提升。这种过程就像是绝望之谷中的及格线 60 分,从 0 分到 60 分相对较容易。但是要从 90 分到 100 分,你可能需要花费更多的时间去学习和弥补自己的知识盲区。

第四,我分享的内容是关于 Gartner 这家著名的技术咨询公司。他们每年都会提供很多技术方案,其中包括一个我们很关注的技术成熟度曲线。这个曲线实际上来自于邓宁-克鲁格效应,用于描述新技术的发展过程,包括从启动期到高峰期再到低谷期,最后进入产品化的平缓期。他们每年都会发布这样的技术成熟度曲线,以便大家了解当前技术处于哪个阶段。

Scott 让我分享关于 Node.js 的内容,起初我是有所拒绝的。但是当我看到知乎上的这篇文章《2021 Node.js 凉透了吗?》时,我非常气愤,所以我决定做此次分享。实际上,Node.js 并没有失去它的魅力。虽然它现在处于产品化的平缓期,就像我们之前提到的那张图所展示的那样。可能许多人感觉近些年来没有什么新的进展和消息,这让一些人觉得 Node.js 的存在感变得有些弱,但事实并非如此。

目前 Node.js 处于产品化的平缓期,主要在做底层稳定性的改进,使其更适用于企业级应用开发。此外,还有很多基础建设正在进行中。 Node.js 技术的历程可以追溯到 2009 年 Ryan 发布,2010 年到达高峰,包括 Express 等框架的推出让其大火一把。在 2012 年 Ryan 离开后,到 2014 年 IO.js 出现,整个生态处于低谷。但是在 2015 年,ES6、IO Merge 的回归,以及 Node FA 的成立,让整个生态经历了快速提升。近年来增长速度有所减缓,但整个 Node.js 生态依然非常良好。之所以进入平缓期,待会会讲到。

在 2018 年,有一个叫做 Node.js 地下铁沙龙的活动,很多 Node.js 的从业者都参加了。在成都站时,现场提出了一个问题,Node.js 是否具备企业级能力。当时,我分享了一些关于 Node.js 做后端微服务的经验,我是感觉到 Node.js 和 Java 相比还存在一些差距。在 SDK 层面,Node.js 和 Java 相比,在中间件等方面还有很大的差距。三年后的今天,Node.js 是否具备企业级能力,仍是大家讨论话题。

在 2019 年,阿里的 Node.js 小组 - NASA 开始进行 All-in-Serverless 的基础建设,这件事情也非常受欢迎,很多 Node.js 人都参与进去了,大家的参与度非常高。

Node.js 在现在的发展中处于怎样的状态?为什么大家很少听到阿里的一些 Serverless 方向建设的消息呢?希望大家能够带着这些问题来参加今天的分享。

今天的分享主要分为三个部分:

  • 第一部分是关于 Node.js 企业级应用赛道的讲解
  • 第二部分是关于 CNCF 的 Game Changer
  • 第三部分则是关于生态的稳定与繁荣

Node.js 企业级应用赛道

首先,我们进入第一个部分,即 Node.js 企业级应用赛道。这个赛道已经非常火热了,竞争非常激烈,可以说已经进入了白热化的状态。如果要做一个企业级应用,我们首先需要看一下框架生态与语言。

在左边是我们的研发态,在右边则是我们的运行态。对于大部分的前端同学来说,他们在前端领域工作,而对于后端同学来说,则需要关注 Node.js 在服务端的运行情况。在研发过程中,我们会有一些脚手架、类型约束、业务逻辑 Code、生态包依赖、依赖框架、工程单测规范等等。

在运行企业级应用时,我们需要考虑的主要是变动层和语言层。变动层是指包括框架和第三方依赖等在内的运行态,而语言层则指编程语言本身。实际上,在运行时我们并不需要太多的东西,因为我们自己编写的代码只占很少的一部分,往往不到整个源代码的 20%。大部分的代码都来自于我们引入的框架和第三方依赖。因此,我们自己的代码量相对较少,也只会对变动层产生影响。

变动层是一个高频迭代的语言 SDK,因为它需要频繁更新以适应业务变更。相反,语言层的更新相对较少,通常只是为了跟 JavaScript 语言对齐或升级 V8 引擎,且是向下兼容的,不会带来太多的问题,因此你不用担心语言升级以后会出现断崖式的更新,虽然也有,但是这个是非常少的。

在部署 Node.js 服务端运行环境或企业级应用时,我们最关心的是变动层,即我们自己编写的代码以及引入的生态依赖和框架。对于语言层,我们则相对放心一些。这是在企业级应用中需要非常关注的两个方面,即研发和运行。然而,如果将 Node.js 放到后端运行并放在整个企业级架构中,我们需要与 Java 进行对齐,这时会发现我们与 Java 之间的差距非常大。

当我们在部署 Node.js 服务端应用程序时,我们最担心的是变动层,也就是我们自己编写的代码、生态和框架。相对而言,我们对语言更加放心,因为它更稳定。在企业级应用程序中,我们需要非常关注开发和运行两个方面。如果将其放置于后端并放置在整个企业级架构中,我们发现与 Java 相比还存在很大的差距和跨度。

Java 的生态能力非常强大,几乎涵盖了所有蓝色方框中的服务。当我们使用 Node.js 进行开发时,我们需要追赶 Java 的 SDK。阿里招募了一些 Node.js 方面的专家来做这个事情,包括 Egg.js 框架和插件,以及为了追赶 Java 的能力而编写的大量 SDK。

The Game Changer CNCF

我们看一下 The Game Changer CNCF。CNCF 的诞生是从 Docker 开始的,从研发阶段到运行阶段,我们在之前的源代码开发过程中,实际上缺少了很多重要信息。例如,进程状态,内存状态,是否会崩溃,而且如果崩溃了,谁来负责重启它?因此,像 Egg.js 这样的框架,作为框架本身,会单独提供进程模型,包括 worker、master 和 agent。因此,在原生状态下,仍然需要担心进程问题。

如果你在服务端运行复杂的 Node.js 应用,你可能会担心环境;如果你运行的是复杂的 Node.js 包,你可能会担心应用对操作系统的底层包的依赖;如果操作系统升级或者更换,你可能会担心应用是否会崩溃。此外,使用 Node.js 很难引用其他语言的功能。Docker 的出现解决了这些问题,它可以提供一个独立的运行环境,使应用与操作系统和其他依赖之间解耦,从而增加应用的可靠性和可移植性。

在 Docker 出现之前,服务端部署的应用都存在着环境差异、调试问题、扩缩容困难等诸多难题,包括 Node.js。但是 Docker 的出现彻底改变了这一局面,Docker 是一个进程模型,把运行时环境隔离起来。

Docker 解决了一些重要的问题。首先,它让本地和服务器端的环境一致性更强了,因为 Docker 的容器可以在不同的地方运行。这解决了 Node.js 调试问题,因为不用担心服务器端的环境是否和本地一样。其次, Docker 的容器是一个进程模型,扩展和缩小非常简单,你可以根据进程的需求来调整容器,而不需要担心 Node.js 如何去抢资源。并且,你可以在一台计算机上部署多个容器。

Docker 的出现对服务端应用开发带来了重大变化,消除了许多心理负担。此外,边车也是一个相对容易理解的概念。在 Docker 中,我们只是将应用程序放在容器中运行,但是我们发现多种语言之间可以共享很多东西,不需要重复开发。例如,Java生态已经非常丰富,而如果我们要将 Node.js 与 Java 在语言层面上对齐,需要编写大量代码。但是,如果我们直接调用 Java 语言,就会变得非常简单。边车的概念就是在 Docker 容器中部署一个 SideCar 进程,它将 Docker 视为宿主,将 SideCar 部署在其中。

进程提供各种能力,包括现在流行的 Dipper 也是这个概念。它将另一个进程部署在容器中,除了你的 Node.js 应用之外,同一个进程还可以调用服务端的其他能力。这使得你的应用更加简单,只需要通过进程间调用调用编车的能力。编车将提供流量控制和各种服务端能力,并通过转发流量将其引入。因此,这里会产生一些概念,例如控制面板和数据面板。

使用 Docker 和 SideCar 的一个重要优势是可以让原本的 Node.js 框架或者 SDK 变得更加简单,只需要处理进程间通信。此外,语言之间很多同质化的工作也可以互相利用,比如利用 Java 的生态,只需将其部署到一个额外的进程中。 Docker 和 SideCar 在 CNCF 中都是很重要的概念,Docker 是 CNCF 的基础,但在 Docker 容器非常多时,就需要解决多容器管理的问题。Docker 公司自己推出了一些容器管理方案,例如 Docker Swarm 和 Docker Kube 之类的方案。

但真正让整个格局产生改变,是谷歌推出的 Kubernetes,它把谷歌在服务器调度控制方面的能力进行了抽象化,并且使用一种叫做 Pod 的概念来管理 Docker 容器,每个节点上的 Kubelet 有一堆的 Pod,Pod 里面再管理多个 Docker 容器。这样,K8s 可以管理整个应用的生命周期,包括应用的生老病死。

基于 K8s 的服务端架构能力解决了服务端部署的问题,并建立了一个庞大的生态系统。现在 K8s 已经成为了企业级应用架构的必备基础设施,被称为云端的操作系统。并且 K8s 支持组件插件的能力,也就是所谓的component。

目前,已经出现了许多不同的解决方案,这些方案在 Docker 中是与编程语言无关的。不管你是用 Node.js、Java、PHP、Python 或其他语言编写应用,都可以通过这些方案进行部署。因此,在 CNCF 的生态系统中,所有的开发语言都可以参与到共同建设中。虽然是针对某些开发语言,提供的是不同的边车能力,但整个 CNCF 生态系统已经具备了在服务端架构方面所需的所有能力。

现在在服务端架构中,各种问题的解决方案已经应运而生,例如流量的限制、降级、压测、灰度等等。这些解决方案都是开源的,所以无论是 Node.js 还是 Java 等应用架构,不再需要担心这些问题。事实上,整个 Java 的生态也被彻底改变了。如果你仍在吹捧 Java,那说明你的视野太狭窄了。

CNCF 已经成为企业级应用架构的最终目标,但它唯一的缺点是太庞大且学习成本较高。如果你熟悉服务端的架构设计和部署,只需要找到对应的 CNCF 开源解决方案即可。在 CNCF 之上,一个问题是在服务端部署时,应用需要有自己的生命周期视角。比如高流量进入或高并发场景下,如何扩容或缩容应用。虽然 CNCF 提供了相关解决方案,但是它太复杂且不是从应用视角出发的。因此,Serverless的概念应运而生。

在服务端架构领域,Serverless 的概念比 CNCF 更早出现,但它们的视角不同。CNCF 正在建设 Serverless 能力,将很多复杂的东西简化,并提供一个应用视角。阿里和微软正在共建的 Knative 就是这样一个方案,它具备应用视角,同时可以依赖底层 Kubernetes 提供的能力。Knative 目前已经进入到 1.0 阶段,并有望被 CNCF 采纳。

随着复杂度的进一步下沉,其实框架的 SDK 变得更薄,Serverless 也处于稳步快速爬升期,大家仍然可以参与共建。如果 Serverless 底层放在 CNCF 上面,那就会发现很多基础建设都已经被 CNCF 干掉了。CNCF 是一个强大的生态联盟,企业级应用架构的基础建设已经被 CNCF 所覆盖。CNCF 是基于 Docker 容器的,因此它与编程语言无关,这让服务端部署应用程序变得更加方便了,即使像 Java 这样的语言也可以很方便地部署在 CNCF 上。

CNCF 是个 Linux 操作系统,与具体编程语言无关。它可以支持 PHP、Node.js、Java 等多种编程语言,逐渐取代了 Java 等过去自带丰富语言生态的方案。如果想在这个生态中生存,你需要贡献出你的开源解决方案,或者适应其他语言的解决方案。每个解决方案中都有大量选择,因此你需要学会拥抱 CNCF,而不仅是绑定在某种编程语言上。在企业级应用架构中使用 Node.js 时,不应只局限于这种编程语言,而应该学习和使用 CNCF 提供的能力和解决方案。

应用的开发部署其实应该优先考虑 Serverless。这是因为 CNCF 是相对比较重的一个东西,引入它可能需要至少启动三台服务器或虚拟机,而这对于一些规模较小的应用来说可能过于冗余。同时,框架层的设计也会变得越来越薄,因为我们需要更加注重应用的开发和部署。

生态的繁荣与稳定

最后我们来谈一下生态的繁荣与稳定。虽然我们引入了 CNCF,但是其中还存在一个潜在风险,即 Node.js 代码中经常会引入生态包的依赖。在最近几年,尤其是 Node.js 全球有这么多的开发者,它现在是一个受到黑客特别关注的语言,尤其是 npm 包,其整个安全事故处于一个高发阶段。我们常见的一种情况是,原作者不想继续维护一个库,于是公开呼吁其他人接手。这时,恶意作者就会接手这个项目,并将自己的恶意代码放入其中进行发布。由于 Node.js 的代码都是相互依赖和引用的,所以恶意代码会快速传播。

最近几年,Node.js 的生态包的依赖和安全性问题一直存在,全球有很多开发者在使用,但同时也容易受到黑客的攻击。例如,replicate.npmjs.com 镜像站点在 2021 年 10 月发现了漏洞,导致私有包被泄露; 2021 年 12 月发现漏洞,攻击者可以任意发布 npm 包,而不需要鉴权。这些问题对整个 Node.js 生态系统构成了极大的威胁。Java 也不例外,比如 log4j2 事件。

事实上,只要你依赖于第三方或第二方,所有语言都可能会遇到这个供应链的安全问题。对于开发者来说,引入每个供应链是否安全是非常无解的。为了保障安全,阿里内部对所有框架提出了维护 2 年的要求。此外,GitHub 和 npm 的团队已被微软收购,并设立了专门的安全团队来负责生态系统的安全。现在整个 npm 生态的安全性已经做得非常好了,恶意代码检测和预警尤其是针对公共包的,10 分钟就可以修复。GitHub 上的依赖树和安全告警也已更新,并引入了 2FA 的鉴权。cnpm 团队在国内也为 Node.js 的发展做出了很多贡献,提供免费高速的下载 npm 包、预编译系统二进制,以及安全的版本列表等。

我觉得所有做开源的工作者都是值得点赞的,尤其是负责任的这些开源的包 owner,Node.js 生态现在已经非常稳定繁荣,其背后离不开这些团队默默的付出。

在国内,有很多人为 Node.js 生态系统做出了杰出的贡献,如朴灵老师、苏千、七念、狼叔、九十、天猪等。这些人中的大部分已经加入了阿里。当一个人深入参与一个生态系统的发展并伴随其历史做出贡献时,这个人的个人提升是非常快的。因此,我们应该尽可能地参与其中,而不是做一个旁观者。

回到我之前提到的两个问题,首先是 2018 年我们在 Node.js 地下铁圆桌会上Node.js 是否具备企业级能力的问题。我认为,虽然 Node.js 目前已经具备企业级应用能力,但是要达到这个水平需要借助 CNCF 的整个生态系统。如果我们想通过语言层面的SDK追赶企业级应用的能力,整个 Node.js 社区里也没有那么多人能够长期持续地投入到这个领域中去。虽然人手很多,但是在开源社区中,很难保证每个人都能够长期投入并保持持续性的贡献。但是借助 CNCF 的生态系统,实现企业级应用能力是非常容易的。

至于让 Node.js 扛双 11 的核心流量这个问题,我认为这完全不是问题,因为 Node.js 已经具备了足够的能力。但是问题在于,是否有人敢去这么做?是否有人能够给我们这个机会?

另外,我也提到了阿里前端共建 Serverless 的事情。当我们最初开始做 Serverless 时,这个技术还处于比较低谷的阶段,很多基础设施都还在开发之中。但是现在,整个 Serverless 基础设施已经非常完备了。

在做 Serverless 的时候,Node.js 的优势并不只是基础设施共建,而是在语言、框架和应用层面都有很多机会,特别是在 ToB 的 SaaS 服务领域,使用 Node.js 可以非常方便,并且得到庞大的生态支持。此外,开源社区也为我们提供了很多的养分,不仅可以参与 Node.js 代码的开发,也可以回馈社区。即使无法参与开发,至少也不应该攻击 Node.js,因为它是一个开源的框架。如果你觉得它不好,你可以参与共建,找到行业内的痛点,成为一个核心开发者。最后提醒大家,安全性问题需要时时留意,不要陷入惯性思维。

尽管有许多人在为我们默默地挡着石头,但如果你不小心被石头砸中了,那也是有可能的。你是要知道其背后还是有一些供应链的问题,因为所有的语言都有这个问题,不仅仅是 Node.js。希望大家能够打造更多的企业级 Node.js 应用的成功案例,这需要大家的努力。Node.js 的发展需要靠整个开源社区的力量。我想起鲁迅说过的话:Node.js 要发展,开源社区靠大家。

最后

最后,我想推荐一本书《点石成金》,这本书对我的前端生涯启发很大。

此外,向大家推荐一下我的知识星球,欢迎小伙伴们一起来学习交流。


前端早早聊
1 声望1 粉丝