第 2 章:创建微服务
本章内容概览:
- 我们的开发哲学
- 构建单一服务的开发环境
- 开发用于视频流的微服务
- 生产与开发环境的准备工作
- 使用 Node.js 部署我们的微服务
本书旨在指导读者构建一个由众多微服务组成的应用程序。然而,在探索多微服务的构建之前,我们首先需要掌握如何开发一个单一的微服务。在本章,我们将一步步构建我们的首个微服务。虽然这个微服务的功能较为基础,但它足以展示整个开发流程,并帮助你将此流程应用于后续的多个微服务开发中。
我们将从一个简单的 HTTP 服务器开始,该服务器负责向网页浏览者提供视频流服务。这是我们构建 FlixTube(一个视频流平台)的起始步骤。虽然视频流技术听起来复杂,但此阶段我们将编写的代码相对简单,没有多大难度。
本书中的微服务均使用 JavaScript 编写,并在 Node.js 环境中运行。需要指出的是,构建微服务不限于任何特定的技术栈,这为技术选型提供了极大的灵活性。你不必局限于使用 JavaScript,Python、C#、Ruby、Java、Go 或任何其他流行语言都同样适用于微服务开发。之所以选择 JavaScript,是因为本书注重实际操作和编程实践。不过,你完全可以根据个人喜好,选用任何一种编程语言来实现微服务。
接下来,我们将简要介绍 Node.js 的基础知识。虽然我们无法涵盖所有细节,但本书将尽可能提供足够的信息以帮助你入门。在本章的末尾,你还会找到一些关于 Node.js 的进阶书籍推荐,以便你可以深入学习。
如果你已经对 Node.js 比较熟悉,你可能会觉得本章的内容较为熟悉,甚至考虑跳过。但我建议你至少快速浏览一遍,因为这里包含了一些关于配置开发环境、准备生产部署及快速迭代开发的重要信息,这些都是我们在整本书中将频繁用到的。
准备好了吗?我们的起点很简单,但内容很快会变得更加精彩。
2.1 新工具介绍
本书将详细讲解多种工具,因此在大多数章节开始时,我们会首先介绍你需要安装的新工具,以便跟随本章的示例进行操作。从第一个微服务开始,下表列出了我们需要的工具:Git、Node.js 和 Visual Studio Code(VS Code)。我们将通过 Git 获取代码,使用 Node.js 运行和测试微服务,并利用 VS Code 编辑代码及管理 Node.js 项目。
在本书的各个章节中,我将会告诉你开发示例时所用工具的具体版本,这将帮助你确保能够顺利跟随示例操作。
这些工具的更新版本通常也可以使用,因为良好的开发工具通常保持向后兼容性。但是,偶尔也可能因为版本更新而导致示例代码无法正常工作。如果遇到这种情况,请通过 GitHub 记录问题通知我(详见下一节)。
表 2.1 本章介绍的工具
| 工具 | 版本 | 用途 |
|---|---|---|
| Git | 2.36.1 | 版本控制是日常开发不可或缺的工具;我们将用 Git 获取第 2 章的代码。 |
| Node.js | 18.17.1 | Node.js 用于运行我们的微服务。 |
| Visual Studio Code (VS Code) | 1.81.1 | VS Code 用于代码编辑和项目管理。 |
当然,你也可以选择其他的集成开发环境(IDE)或文本编辑器进行代码编辑。我推荐使用 VS Code,因为它功能强大且广受欢迎。
2.2 获取代码
本书提供了许多实际工作的示例项目。这些项目的代码都存放在 GitHub 上,你可以从那里克隆或下载代码库,以便跟随书中的示例进行学习。我强烈建议你在阅读本书的同时运行这些示例,这是获取实践经验和最大化学习效果的最佳方法。
按照惯例,这些示例都非常容易设置和运行。一旦你掌握了基础操作(我们会进行详细介绍),你会发现运行这些示例很简单。随着我们逐步深入,示例的复杂度会逐渐增加,但我将努力保持示例的易理解性,详细解释其工作原理,并指导你如何将它们运行起来。
要访问《微服务启动手册(第二版)》的 GitHub 组织页面,请在浏览器中打开 http://mng.bz/vPVr 。从第 2 章开始,每章都有自己的代码库,地址为 http://mng.bz/46Yv 。在每个代码库中,你可以找到按章节组织的示例项目。如果在使用代码时遇到任何问题,或在尝试运行它们时遇到困难,请在 GitHub 上相应的代码库中记录问题,我将帮助你解决。
2.3 选择 Node.js 的理由
在本书中,我们将使用 Node.js 来构建微服务。为什么选择 Node.js?在微服务的开发中,一个显著的优势是我们能够自由选择技术栈。Node.js 不仅是我个人偏好的技术,同时也有其他一些原因促使我选择它。
通过 Docker 构建微服务(将在第 3 章详细讨论)允许我们从多种技术栈中挑选,组成一个多样化的应用程序。虽然这种方式听起来可能有些复杂,实际上这种技术的多样性让我们有更多自由去为不同的需求选择最适合的技术栈。
注意 Node.js 专为网络应用设计,具有高性能特性,非常适合用来构建微服务。鉴于我们计划开发多个服务,选择一个能够简化工作的平台无疑是明智的选择。
Node.js 的流行度和知名度也是选择它的一个重要原因。这或许听起来微不足道,但实际上非常关键,因为围绕 Node.js 形成了一个包含丰富人力资源、工具和其他资源的生态系统。拥有一个庞大的支持社区意味着在遇到困难时更容易找到帮助,并在持续的软件开发过程中得到支持。
Node.js 从设计之初就是为了微服务的需求。其名称“Node”暗示了它在构建基于网络的分布式应用程序中的作用。自 2009 年 JavaScript 从浏览器端扩展到服务器端以来,它已经证明了自己是一个功能强大的服务器端编程语言。
Node.js 旨在创建小型、高效且轻量的服务,避免了许多其他平台可能带来的复杂和不必要的负担。在 Node.js 中搭建一个 HTTP 服务器既简单又直接,这使得我们能够迅速启动新的微服务,这对于我们计划构建的众多小型服务来说,是一个很大的优势。Node.js 的便利性还体现在,你不需要投入大量时间就可以学会如何编写一个基本的微服务,你很快会发现,使用 Node.js 只需要少量代码即可搭建起一个微服务。
JavaScript 还支持全栈开发。今天,几乎所有地方都可以看到 JavaScript 的身影。我们可以使用它在后端构建微服务,也可以在基于 Web 的前端使用(这是 JavaScript 的发源地)。此外,JavaScript 还可以用于桌面开发(例如 Electron 和 Tauri)、移动开发(例如 Ionic/Capacitor)和嵌入式开发(例如物联网设备),就像我在之前的书《Data Wrangling with JavaScript》中展示的,即使是通常由 Python 主导的数据处理领域,JavaScript 也能大显身手。尽可能多地使用 JavaScript 意味着我们可以在应用程序的任何部分工作,而无需进行思维上的转换。
如今,许多开发人员(包括我自己)选择使用 TypeScript,这是一种基于 JavaScript 的语言,引入了静态类型系统。TypeScript 的优势在于它的灵活性,可以灵活地结合静态和动态类型,以达到最佳效果。
Node.js 的另一个显著特性是 npm(Node Package Manager),这是一个命令行工具,用于安装 Node.js 的包(包括代码库和命令行工具)。虽然这与构建微服务没有直接关联,但拥有一个优秀的包管理器和丰富的开源包资源非常有助于开发。作为一个开发人员,我的优势之一是能够轻松访问超过 2,625,124 个现成的代码库,通常我需要的功能只需在 npm 上简单搜索即可找到。
注意 Node.js 是开源的,你可以在 GitHub 上查看其源代码: https://github.com/nodejs/node 。
什么是 npm?
如前所述,npm 是 Node 包管理器。它是一个命令行应用程序,与 npm 的在线仓库进行通信,允许你在 Node.js 项目中管理第三方包。使用现成的包可以快速解决问题,否则你可能需要编写大量代码来实现这些功能!你可以在 npm 的官网 www.npmjs.com 上搜索并管理这些包。
2.4 我们的开发哲学
在正式开始编程前,我想先向你介绍一下我们将在本书中遵循的开发哲学。这种哲学将在书中反复体现,因此了解其基本原则非常有益。这里,我用以下三点来概括我们的开发哲学:
- 迭代开发
- 保持代码始终可运行
- 从简到繁
迭代开发 是我们方法的核心。这里的迭代,我指的是个人编码中的小步迭代,而不是通常在敏捷开发中所说的大规模迭代(尽管大规模迭代也很有其价值)。通过不断的个人迭代,我们逐步构建和完善代码,正如图 2.1 所示。这种工作方式让我们能够及时获得反馈,及时发现和纠正偏差。迅速的迭代有助于我们的工作与不断变化的目标保持一致。
注意 经常进行小规模的代码增量调整,对软件开发过程至关重要。
在每次迭代中,我们只编写少量的代码,具体多少取决于我们的任务和其难度。关键是要保持代码量足够小,以便我们能够轻松管理和测试刚编写的代码。
每一次迭代都应产出可工作且经过测试的代码,这是非常关键的一点。你是否有过这样的经历:写了很长一段代码,然后花费几小时甚至更久的时间去调试使其工作?如果我们坚持在小的、经过良好测试的代码增量中工作,那么当一天工作结束时,你将得到一大段可工作的代码,如图 2.1 所示。

保持代码始终可运行。如果我们始终在小的、易于测试的代码增量中工作,我们很少会遇到问题。当你一次性输入大量代码时,很可能会遇到许多阻碍代码运行的难题。即使代码看似可运行,实际上也可能隐藏着许多尚未发现的问题。当我们的代码始终保持可工作状态,一旦遇到问题,我们可以轻松地回退到上一次迭代的状态。由于每次迭代的代码量都很小,即使需要回退,我们也不会失去太多的进展。
从简到繁 是我们开发的基本原则。我们应该从编写最简单的代码开始,并逐步通过迭代使应用程序更加复杂。任何应用程序都会随着时间的推移变得复杂,这是不可避免的,但我们不应该从复杂开始。不要试图一次性构建一个复杂的系统——这往往是不利的。
注意 应用程序最终可能会变得复杂,但这并不意味着它们必须从复杂开始。每次代码更改都应该是简单的,避免在任何单次迭代中引入过多复杂性。
从最简单的代码开始,然后通过一次次的迭代使其逐渐复杂化,如图 2.2 所示。不要急于接受复杂性。尽可能地保持简单。随着我们的应用程序变得越来越复杂,我们会引入工具、技术、流程和模式来帮助我们管理这种复杂性。

微服务是管理复杂性的工具。此外,每个具体的微服务应该保持简单。它应该是小巧的。对现有微服务进行小的更新应该是容易的,向现有应用程序添加新的微服务也应该是轻而易举的。即使应用程序本身变得极其复杂,这些原则仍然适用。
即使我们的代码变得更加复杂,这并不意味着我们的迭代也必须变得复杂。我们应该努力保持每次代码修改尽可能简单。简单的更改更易于理解、测试和集成。所有这些都提高了系统在演变中继续按预期工作的可能性。
提示 在处理复杂应用程序中的问题时,不要害怕将问题从应用程序中提取出来,并在更简单的环境中重现它。如果能用更少的代码隔离一个问题,这个问题就更难隐藏。
如果我们在复杂应用程序中遇到难以解决的问题,我们现在有了新的选择。如前面图 2.2 所示,我们可以随时将问题代码从复杂应用程序中提取出来,并在更简单的环境中重新检验。
使用 JavaScript 编码时,这一点尤为容易实现。我们可能会在自动化测试中加载代码,在那里我们可以反复运行代码以进行故障排除和修复。如果这不可行,我们可以将代码提取到单独的 Node.js 项目中,以隔离问题,从而更容易地解决。我经常使用我自己开发的 Data-Forge Notebook( www.data-forge-notebook.com )来达到这个目的。
但如果代码不那么容易提取怎么办?在这种情况下,我喜欢拆解围绕问题代码的应用程序,并尽可能多地将代码提取出来,直到问题被隔离。当你隔离了一个问题时,它就无处遁形。识别问题通常比修复问题花费更多时间。因此,找到更快的方法来定位代码中问题的位置是提高生产力的最佳方法之一。我们将在第 11 章中进一步讨论调试技巧。
这也是微服务模式值得赞赏的地方。我们的应用程序已经是模块化的,因此我们应该能够容易地剔除非必要的微服务。然而,以这种方式去除代码是一种高级技术,可能容易导致应用程序出现中断!
我在这里介绍我的开发哲学,因为我相信它可以帮助你成为一个更优秀、更高效的开发人员。通过小而经过良好测试的增量来发展我们的软件是我们的主要目标。我们正在对代码进行一次从工作状态到工作状态的迭代之旅。在任何时候,我们的代码都不应该被根本性地破坏。
你将在本章和整本书中看到这种哲学的实际应用。从简单开始。从小开始。通过小改动进行迭代。保持代码的可工作状态。不知不觉中,你就会构建出一个庞大而复杂的系统!但这不是一蹴而就的。这是通过一系列小的改动,最终累积成为一些重要的成就。
注意 想要了解更多关于如何实践这种开发哲学,可以查阅我即将出版的《快速全栈开发》( https://rapidfullstackdevelopment.com/ ),在那里我将展示这一哲学的全面实现。
2.5 构建单服务开发环境
为了开发和测试一个微服务,我们首先需要搭建一个开发环境。这使我们能够编写和修改代码,并在本地运行它来验证其功能。在本章中,我们将重点构建一个单一的微服务,并使用 Node.js 直接在开发机上运行它。我们将使用 VS Code 或你选择的其他 IDE 或文本编辑器来编辑代码。
Node.js 安装简单,可在所有主流操作系统上运行,因此你可以选择 Linux、Windows 或 macOS 来开发你的微服务(详见表 2.2)。
单独运行一个服务在 Node.js 下非常简单,你将在本章后面部分看到这一点。但当我们开始开发和测试多个微服务(将在第 4 章讨论)时,情况会变得更加复杂。到那时,我们将开始使用 Docker(从第 3 章起)。现在,我们的焦点是直接在 Node.js 下运行第一个微服务。
即使在我们开始开发和测试多个微服务之后,有时候还是需要从应用程序中提取一个微服务并单独运行它,以便我们可以专注于这个独立的部分,而无需担心整个应用程序及其所有的复杂性。拥有一个单服务开发环境不仅在早期阶段方便,而且在整个开发周期内都是一种便利。
表 2.2:Node.js 运行选项
| 平台 | 说明 |
|---|---|
| Linux | Node.js 最初是为 Linux 设计的,因此在这个平台上运行表现出色!在本书中,我将主要展示在 Ubuntu Linux 上的命令操作。如果你也在使用 Ubuntu 或其他 Linux 发行版,那么跟随本书的示例将会非常顺利。 |
| Windows | Node.js 在 Windows 上也运行良好。实际上,我大部分的日常开发、测试和问题排查都是在 Windows 上完成的。 |
| macOS | Node.js 在 macOS 上同样运行良好。 |
注意:当你仅使用 Node.js 时,你可以在任何平台上运行它,实际上没有哪个平台有明显优势。
图 2.3 显示了我们单服务开发环境的布局。我们将在 VS Code 或其他编辑器中编写代码。我们的微服务项目是一个 Node.js 项目,包括 JavaScript 代码。在 Node.js 环境下执行我们的项目,将会启动一个运行中的微服务实例。所有这些都将在我们选择的主操作系统(Linux、Windows 或 macOS)上进行。

2.5.1 安装 Git
在这本书中,所有的示例项目和代码都托管在 GitHub 上的 “Bootstrapping Microservices” 组织下(详见第 2.2 节链接)。图 2.4 展示了代码库的结构,其中每个子目录(如 example-1、example-2)都包含一个完整的可运行项目,这样你就可以轻松地跟随书中的示例,无需手动输入所有代码。

图 2.4 GitHub 上的每个示例项目都是一个完整的可运行项目,你可以自己运行它们。
下载这些代码的最简单方法是从 GitHub 上将其下载为 ZIP 文件。你可以访问相应的代码库(例如第 2 章的代码库),找到“克隆或下载”按钮,点击后选择“下载 ZIP”。
当然,最好的获取代码方式是使用 Git 克隆代码库。首先,你需要安装 Git。你可能已经安装了它,比如说如果你像我一样每天都在使用它。或者,如果你使用的是预装了 Git 的 Linux 发行版,或者在 macOS 上安装了包含 Git 的 Xcode,那么你可能已经有了 Git。
要检查是否已安装 Git,可以在终端中(Windows 上则在命令提示符或更好的选择是安装 Windows Terminal)运行以下命令:
git --version
如果已安装 Git,它会显示版本号,如:
git version 2.36.1
如果你还没有安装 Git,安装过程非常简单。你可以根据 Git 官网( https://git-scm.com )上的指南下载并安装适合你平台的版本。
初学者使用命令行?
作为软件开发人员,使用命令行是一种非常有效和高效的工作方式。虽然使用 UI 和可视化编辑器完成日常任务非常便捷,但对于更复杂或定制化的任务,熟练使用命令行是必需的。如果你是初学者,建议先学习一个教程,了解你的操作系统命令行的基本使用方法。
2.5.2 克隆代码库
安装 Git 后,你可以开始克隆本书各章的代码库。例如,你应该从克隆第 2 章的代码库开始,以便跟随本章内容:
git clone https://github.com/bootstrapping-microservices-2nd-edition/chapter-2
这条命令会从 GitHub 上把代码库的副本下载到本地硬盘上的 chapter-2 目录中。在后续的章节,我将不再详细说明如何克隆代码库,但每章开始时我会指明如何获取该章的代码;然后你可以使用 Git 来获取你自己的副本。如需回顾如何使用 Git 克隆代码库,随时回到这里查看。
2.5.3 获取 VS Code
我使用 VS Code 完成所有编码工作,并向你推荐它,因为它是一个优秀的代码编辑环境。你可以在 VS Code 的官网 https://code.visualstudio.com 上找到适用于 Windows、Linux 和 macOS 的下载与安装指南。
我之所以喜欢 VS Code,是因为它轻量级、性能优异且高度可配置。它也广泛用于 Node.js 和 JavaScript 项目。虽然你无需为本书安装任何额外的插件,但值得一提的是,VS Code 有大量易于安装的插件,适用于不同的编程语言和任务。你还可以根据自己的开发需要自定义 VS Code。
当然,如果你已经有了自己喜欢的 IDE 或文本编辑器,完全可以继续使用,因为实际上它对你的工作影响不大。当我在书中提到 VS Code 时,你只需想象它是你喜欢的那个编辑器。
2.5.4 安装 Node.js
要运行我们的微服务,你需要 Node.js。因为本书中的所有示例微服务都是基于 Node.js 项目的,所以这是必不可少的步骤。所有的代码示例都用 JavaScript 编写,并在 Node.js 上运行。如果你已经安装了 Node.js,可以通过以下命令在终端中检查其版本:
node --version
v18.17.1
npm --version
9.6.7
这些是我当前使用的 Node.js 和 npm 的版本。你可以使用这些版本或更高版本。
注意 我们使用 npm 命令来安装第三方包。安装 Node.js 时,你会同时得到 npm。
在任何平台上安装 Node.js 都非常简单,你可以在 Node.js 的官网( https://nodejs.org )上找到下载和安装指南。这个过程并不复杂,你不应遇到任何问题。
如果你已经安装了 Node.js 并想升级到新版本,或者你想管理多个 Node.js 版本,你可能会对 nvm(Node 版本管理器)感兴趣。在接下来的边栏中有详细介绍。
安装 Node.js 后,打开终端,双重确认它是否正确安装。为此,检查版本号:
node --version
npm --version
现在我们已经安装了 Node.js,就可以开始构建并运行我们的第一个微服务了。
了解你使用的版本很重要!
使用 --version 参数检查是否已安装某个工具是一个好方法,但了解你使用的具体版本也非常重要。当你在处理实际项目时,确保在开发和生产环境中使用相同的版本至关重要,这是确保你的代码在生产环境中能正常运行的最佳方式。
需要运行不同版本的 Node.js?
如果你需要维护多个基于不同 Node.js 版本的生产应用,或者你只是在开发一个已有很长历史的应用,并且不同的微服务使用不同版本的 Node.js,使用 nvm(Node 版本管理器)来安装和切换不同版本的 Node.js 是一个很好的选择。
实际上,有两个不同的 nvm 应用程序,具体选择哪个取决于你的操作系统。以下是获取设置指南的链接:
- 对于 Linux 和 macOS: https://github.com/nvm-sh/nvm
- 对于 Windows: https://github.com/coreybutler/nvm-windows
这需要你熟练使用命令行,不适合初学者。如果你不熟悉命令行,可能需要先学习相关技能。
2.6 构建一个用于视频流的 HTTP 服务器
现在我们有了开发环境,可以构建第一个微服务了。这不是一个困难的项目,我们只是构建它来展示创建一个基本微服务的过程。这是创建我们示例微服务应用程序 FlixTube 的第一步。在阅读本章时,你可以跟随代码,逐行输入代码,或者先阅读然后尝试在 GitHub 的第 2 章代码库中提供的示例项目。
我们构建的微服务是一个简单的视频流服务。视频流可能听起来很难——在真实的生产应用程序中它确实可以变得复杂——但我们从更简单的东西开始。你可能会惊讶于我们需要多么少的代码来实现这一点。
图 2.5 展示了本章项目最终结果的输出。我们的微服务通过端口 3000 和 /video 路径向浏览器传输视频。我们可以通过将浏览器指向 http://localhost:3000/video 直接在浏览器中观看视频。
在图 2.5 中,你可以看到我们使用 Chrome 浏览器观看视频。我们使用的示例视频是从 https://sample-videos.com 下载的。这里我们使用最短的视频,但你可以随意下载较大的示例视频进行自己的测试。在第 2 章代码库中的 videos 子目录下包含了短的示例视频。如果你下载其他视频进行测试,可以将它们复制到这个目录中。

要创建我们的微服务必须遵循以下步骤:
- 为微服务创建一个 Node.js 项目。
- 安装 Express 并创建一个简单的 HTTP 服务器。
- 添加一个 HTTP GET 路由 /video 的处理程序,用于检索视频流。
在创建这个基本的第一个微服务后,我们将简要讨论如何配置我们的微服务。然后,我们将介绍一些生产和开发设置的基本知识。
2.6.1 创建一个 Node.js 项目
在开始编写代码之前,我们需要一个 Node.js 项目来存放代码。我们即将创建的项目结构如图 2.6 所示。这是一个基本的 Node.js 项目,包含一个入口脚本文件 index.js。你还会看到 package.json 和 package-lock.json 文件,这些文件用于跟踪项目的依赖项和元数据。依赖项本身是安装在 node_modules 目录下的可下载代码库。让我们开始创建这个项目吧!

定义:一个 Node.js 项目包含源代码和配置信息。这是我们编辑和创建微服务功能的代码的地方。
如果你是从头开始创建项目(而不是直接从 GitHub 运行代码),你需要首先为项目创建一个目录。在 Linux 和 macOS 上,你可以使用 mkdir 命令来做这件事:
mkdir my-new-project
在 Windows 上,你可以使用 md 命令:
md my-new-project
使用 cd 命令进入新创建的目录:
cd my-new-project
我们现在准备创建一个空的 Node.js 项目。这意味着我们需要创建 package.json 文件。你可以使用 npm init 命令来完成这个步骤:
npm init -y
使用 -y 参数意味着在初始化项目时我们不需要回答任何交互式问题,这使得创建项目过程更为简单和快速。
执行 npm init 后,我们现在有了一个 package.json 文件,其中所有字段都设置为默认值。你可以稍后回来修改这些字段,以使它们更适合你的项目。现在,我们可以继续保持默认设置。
代码清单 2.1 新创建的 Node.js 项目的 package.json 文件
{
"name": "my-new-project", // 包名。通常是项目目录的名称,此处为我们创建的 my-new-project 目录。
"version": "1.0.0", // 版本号,对于将包发布到 npmjs.com 等平台非常重要。
"description": "",
"main": "index.js", // 默认的入口文件。这个文件我们还未创建。
"scripts": {
"test": "..." // 这里定义 npm 脚本,我们会在后续章节中详细讨论。
},
"keywords": [],
"author": "",
"license": "ISC" // 发布到 npmjs.com 时需要填写的授权信息。
}
创建 Node.js 项目之后,建议你使用 VS Code 打开项目文件夹,并打开 package.json 文件来浏览新项目。一旦你在 VS Code 中打开了项目,就可以开始往项目中添加代码了。
package.json 与 package-lock.json 的比较
尽管 package.json 文件是由 npm 自动生成并更新的,你也可以手动编辑它以修改项目的元数据和 npm 模块依赖关系。
通常情况下,package.json 并不会为依赖项指定确切的版本号(尽管你也可以这样设置),而是标明每个依赖项的最低版本要求或一个版本范围。此外,package.json 只跟踪项目的顶级依赖项,不需要你手动指定这些依赖项的依赖项,这会自动处理。这使得 package.json 文件更加精简和易于管理。
package.json 的缺陷是,你和你的团队成员可能最终会运行不同版本的依赖项,甚至可能与生产环境中使用的版本不同。
这种情况通常发生是因为 package.json 通常不会锁定确切的版本号,所以当你运行 npm install 时,可能会根据当时的环境安装不同版本的依赖项。这种不确定性是问题复现的障碍,特别是在生产环境中。
为了解决这个问题,npm 从版本 5 开始引入了 package-lock.json。这个文件是自动生成的,通常不手动编辑。它的目的是锁定整个依赖树(包括依赖项的依赖项)及每个依赖项的确切版本。
将 package-lock.json 文件提交到你的代码库是非常重要的,这可以确保团队成员和生产环境都使用相同的依赖版本,从而使项目配置保持一致。
2.6.2 安装 Express
为了实现我们的微服务并使其能够以 HTTP 服务器(或称为 Web 服务器)的形式运行,响应浏览器发出的播放流视频的 HTTP 请求,我们将使用 Express 框架。
注意:Express 是在 Node.js 上构建 HTTP 服务器的事实上的标准框架。使用 Express 来创建 Web 服务器,比单独使用 Node.js 的底层 API 要简单得多。
Express 是一个广受欢迎的框架,用于在 Node.js 上构建 HTTP 服务器。你可以在 Express 的官网 http://expressjs.com/ 上找到详细的文档和示例。虽然我们完全可以只使用 Node.js 的内置功能来构建 HTTP 服务器,但使用 Express 允许我们以更高层次的抽象、更少的代码实现,并且无需直接操作 Node.js 的低级 API。
此外,使用 Express 还是一个学习如何为我们的微服务安装 npm 包的好机会。npm 是 Node.js 的包管理器,为我们提供了广泛的库和框架,包括 Express,这些都可以帮助我们更高效地完成任务,否则我们需要编写更多的代码并可能引入更多的错误。通过下面的命令,我们可以从终端安装最新版本的 Express:
npm install express
此命令将 Express 安装到我们的项目中。对于本书,我选择使用 Express 的 v5 beta 版本:
npm install [email protected]
Express v5 beta 版本支持异步路由处理程序,这将简化我们后续的代码编写。我希望在你阅读本书时,v5 已经正式发布,不再是 beta 版本。你不需要过于担心 Express v4 和 v5 之间的差异;除了对异步路由处理的支持外,我没有发现其他显著的差异,而且本书中的所有代码示例都应在两个版本中运行良好(尽管 Express v4 处理异步错误的方式稍有不同)。
--save 参数已经不是必需的,因为现在它是 npm 的默认行为。我在这里明确使用了 --save 参数来强调其功能,但实际上你在现代版本的 npm 中使用时可以省略它。
图 2.7 展示了我们的项目中 node_modules 目录下创建的 express 子目录,你会发现除了 Express 外,还有许多其他包被安装了。这些是 Express 所需的依赖项,npm 已经自动为我们处理了这些安装。

代码清单 2.2 更新后的 package.json 文件展示安装了 Express
{
"name": "example-1",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "..."
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^5.0.0-beta.1"
}
}
通过 package.json 文件跟踪依赖项,你可以轻松地将项目和代码分享给其他开发者(例如团队成员),这样他们就可以复制你的工作环境。这也意味着我可以将代码提供给你,你可以轻松地让它运行。
例如,如果你想运行 example-1,首先需要根据第 2.5.2 节的指南克隆第 2 章的代码库。然后在终端更改到代码库的目录:
cd chapter-2
接着,更改到你想要运行的特定示例的目录,这里是 example-1:
cd example-1
然后,你可以使用 npm 安装所有依赖项:
npm install
使用 npm install 命令(没有指定具体的包)将安装 package.json 中列出的所有依赖项。在这个例子中,只列出了 Express,因此只会安装 Express 及其依赖项。对于本书中的其他示例,可能会列出更多依赖项,但每个示例只需调用一次 npm install 就足够了,可以安装运行每个 Node.js 示例项目所需的所有内容。
2.6.3 创建 Express 框架
在添加视频流功能到我们的微服务之前,我们首先需要设置一个标准的 Express HTTP 服务器。代码清单 2.3(chapter-2/example-1/src/index.js)展示了一个基础的 Hello World 示例,这是遵循官方 Express 入门指南(
https://expressjs.com/
)得到的结果。
这个示例虽然代码量少,但为我们的项目提供了一个简单的起点。你现在应该在你的 Node.js 项目的 src 目录下创建一个 index.js 文件,并填入以下代码。如果你认为直接手写代码过于繁琐,可以直接从第 2 章的代码库中的 example-1 查看我已为你准备好的版本。
代码清单 2.3 最简单的 Express Web 服务器
const express = require('express'); // 引入 Express 库
const app = express(); // 创建一个 Express 应用实例
const port = 3000; // 我们的 HTTP 服务器将监听端口 3000
app.get('/', (req, res) => { // 为 HTTP GET 请求到根路径 '/' 设置一个路由处理器
res.send('Hello World!'); // 当访问根路径时,在浏览器中显示 "Hello World!"
});
app.listen(port, () => { // 启动服务器,监听指定的端口
console.log(`Example app listening at http://localhost:${port}`);
});
文件 index.js 被命名为此,因为它是 Node.js 应用的标准入口点之一。我们也可以将其命名为其他名称如 main.js 或 server.js。通过将文件命名为 index.js,我们赋予它一个许多 Node.js 开发者会立即识别的主文件名称。
我们将 index.js 文件放在 src 目录中,以帮助将源代码文件(src 是 “source” 的缩写)与配置文件和其他文件分离。虽然目前我们可能不需要这样的组织结构,但为未来可能的扩展提前设置是有益的,尤其是在下一章中我们会更多地使用到。这个目录不一定要命名为 src,你可以根据喜好命名,但 src 是一个常用的名称。记得在 package.json 文件中更新 main 字段,指向 src 目录下的 index.js。
端口号使我们能够在同一台计算机上运行多个 HTTP 服务器,每个服务器都有自己的端口号,避免相互冲突。选择端口 3000 是一种常见的约定,虽然这只是开发时的习惯,在生产环境中,我们通常希望应用运行在标准 HTTP 端口 80 上。稍后我们将讨论如何配置微服务启动时的端口号。
如果端口 3000 已被占用,你可以选择其他端口,如 4000 或 5000。当我们同时运行多个微服务时,而不是单一服务,我们会使用从 4000 开始的一系列端口号(例如 4000、4001 等)。现在,我们已准备好运行这个极其简单的 Web 服务器。
什么是 index.js?
按照惯例,index.js 文件通常作为 Node.js 应用程序的主入口点。在尝试理解现有的 Node.js 项目时,通常应首先查看 index.js 文件。
2.6.4 运行简单的 Web 服务器
要测试我们刚创建的 HTTP 服务器,可以从终端运行。首先,我们需要确保我们在 Node.js 项目的同一目录中。如果你从头开始构建项目,则必须更改为你创建的目录。例如:
cd my-new-project
否则,如果你使用的是第 2 章 GitHub 代码库中的代码,应更改为 example-1 目录:
cd chapter-2
cd example-1
现在,你可以使用 Node.js 运行 JavaScript 代码并启动 HTTP 服务器:
node src/index.js
如果你在 Windows 上运行,可能需要将正斜杠更改为反斜杠。我在编写本书第二版时使用的是 Windows 11,正斜杠对我来说有效,但在旧版本的 Windows 上可能不起作用。
我们在这里所做的是使用 src/index.js 作为参数运行 Node.js。我们告诉 Node.js 运行我们的脚本文件。Node.js 执行此文件中的 JavaScript 代码,如果成功,我们会在终端中看到以下输出:
Example app listening at http://localhost:3000
我们现在可以测试这是否有效。打开你的 Web 浏览器并指向 http://localhost:3000 。你应该会看到显示的 “Hello World” 消息。
我们现在有一个基本的 HTTP 服务器在运行,现在是时候向它添加视频流了。当你准备好停止运行的 HTTP 服务器时,返回运行它的终端,并按 Ctrl-C 退出 Node.js 应用程序。
2.6.4 运行基础 Web 服务器
要测试我们新建的 HTTP 服务器,首先确保你位于 Node.js 项目的正确目录中。如果你是从头开始构建项目,就需要切换到你创建的项目目录:
cd my-new-project
如果你是使用第 2 章的 GitHub 代码库中的代码,应切换到 example-1 目录:
cd chapter-2
cd example-1
现在,你可以使用 Node.js 来运行你的 JavaScript 代码并启动 HTTP 服务器:
node src/index.js
如果你在 Windows 上运行,路径中的斜杠可能需要调整。在我使用 Windows 11 编写本书时,正斜杠是有效的,但在旧版 Windows 中可能需要使用反斜杠。
执行上述命令后,Node.js 会运行指定的脚本文件 src/index.js。如果一切顺利,你将在终端看到如下输出:
Example app listening at http://localhost:3000
这表明服务器已启动并在监听 HTTP 请求。你现在可以打开浏览器,访问 http://localhost:3000 来测试服务器。你应该能看到页面上显示“Hello World”。
你的基础 HTTP 服务器已经在运行,下一步是将视频流功能添加进来。当你想停止服务器时,可以回到运行服务器的终端并按 Ctrl-C 来退出 Node.js 程序。
2.6.5 添加视频流功能
在代码清单 2.3 中,我们设置了一个简单的路由处理器,它只返回“Hello World”。现在我们将修改它,创建一个新的 REST API 路由来向浏览器流式传输视频。REST API(表现层状态转换应用程序编程接口)可能听起来复杂,但其实质很简单。它本质上是一组用于与后端系统进行交互的 HTTP 路由处理器。
通常,REST API 的路由会返回 JSON 数据,但我们将添加一个新的路由来返回视频流。你可以在图 2.8 中看到这个过程。图中显示了我们的 HTTP 服务器如何从文件系统读取视频,并通过端口 3000 和 /video 路由将视频传输到 Web 浏览器。

图 2.8 Web 浏览器通过 /video 路由与我们的微服务交互
以下是图片中的文字及其翻译:
- Our HTTP server is listening on port 3000 for connections from a web browser.
- 我们的 HTTP 服务器在端口 3000 上等待来自 Web 浏览器的连接。
- The streaming video is made available on the route /video.
- 视频流通过 /video 路径提供。
- Our code running in the HTTP server streams the video.
- 在 HTTP 服务器中运行的代码负责视频流的传输。
- The video is streamed from the local filesystem.
- 视频从本地文件系统传输。
我们定义了一个新的 /video 路由,如代码清单 2.4(chapter-2/example-2/src/index.js)所示。如果你正在跟随书中的步骤,可以更新你之前创建的 Express 框架。否则,可以在第 2 章的代码库 example-2 中查看更新的 index.js 文件。
代码清单 2.4 使用 Node.js 的简单视频流服务器
const express = require('express');
const fs = require('fs'); // 引入内置的 fs 库以使用 Node.js 的文件系统 API
const app = express();
const port = 3000;
app.get('/video', async (req, res) => {
const videoPath = '../videos/SampleVideo_1280x720_1mb.mp4'; // 视频文件的路径
const stats = await fs.promises.stat(videoPath); // 获取视频文件的大小
res.writeHead(200, {
'Content-Length': stats.size,
'Content-Type': 'video/mp4',
});
fs.createReadStream(videoPath).pipe(res); // 创建视频流并发送到浏览器
});
app.listen(port, () => {
console.log(`Video stream app listening at http://localhost:${port}`);
});
这段代码演示了如何使用 Node.js 的流功能从文件系统读取视频文件并将其流式传输到浏览器。我们在 src/index.js 中创建了一个可以将视频文件作为流发送的路由。这是一个简单的起点,专注于我们微服务应用程序 FlixTube 的核心功能:视频流。视频文件位于 example-2 下的 videos 子目录中。
要运行这段代码,首先切换到 example-2 子目录:
cd chapter-2/example-2
然后安装所有必需的依赖项:
npm install
现在可以启动视频流服务:
node src/index.js
打开浏览器访问 http://localhost:3000/video 观看视频,这将类似于之前在图 2.5 中所示的样式。
为了测试本书的代码,我使用了 Chrome 浏览器。我发现这样简单的视频流在旧版 Safari 浏览器上不起作用。有关如何在 Safari 中实现视频流的详细信息,请参考我的博客文章: www.codecapers.com.au/video-streaming-in-safari 。在第 9 章中,我们将更详细地讨论如何测试我们的微服务。
2.6.6 配置我们的微服务
现在,我们需要花些时间考虑如何配置微服务。这是一个关键的步骤,有助于我们更有效地使用和管理微服务。在后续章节中,我们将看到如何通过配置将多个微服务串联起来工作。首先,让我们来看一个关于如何配置微服务的简单例子。
我们需要一种方法来在启动 HTTP 服务器时指定使用哪个端口号。可以通过多种方式配置微服务,如使用配置文件或命令行参数。这些方法都很有用,但还有一种方法已成为配置微服务的标准,并且受到我们将要使用的所有工具的良好支持。
我们将通过环境变量来配置我们的微服务。具体来说,我们需要一个环境变量来设定 HTTP 服务器的端口号。图 2.9 展示了我们如何将 PORT 环境变量用于我们的微服务配置。

在 Node.js 中使用环境变量来配置微服务非常简单。我们只需访问 process.env 对象的相关字段。你可以在代码清单 2.5(摘自 chapter-2/example-3/src/index.js)中看到这个方法的实际应用,我们的代码使用 process.env.PORT 来获取端口号的值。如果没有提供 PORT 环境变量,代码将抛出错误。我倾向于添加这样的错误检查,以确保微服务明确说明它所需的配置,这样我们就不会在生产环境中意外地启动一个未配置的微服务。如果我们试图这样做,微服务会拒绝启动,并告诉我们原因。
我认为,比起在可能配置错误的情况下运行微服务,服务拒绝启动并提供错误信息是一个更好的选择,因为这样可以避免我们浪费时间去调试代码,试图找出问题所在。
// 代码清单 2.5 配置微服务
const express = require("express");
const fs = require("fs");
const app = express();
if (!process.env.PORT) {
throw new Error("PORT 环境变量未设置,无法启动服务。"); // 如果没有设置 PORT 环境变量,则抛出错误
}
const PORT = process.env.PORT; // 从环境变量中获取端口号
app.get("/video", async (req, res) => {
const videoPath = "../videos/SampleVideo_1280x720_1mb.mp4";
const stats = await fs.promises.stat(videoPath);
res.writeHead(200, {
"Content-Length": stats.size,
"Content-Type": "video/mp4",
});
fs.createReadStream(videoPath).pipe(res);
});
app.listen(PORT, () => {
console.log(`服务正在端口 ${PORT} 上运行`);
});
现在,让我们运行此代码:
cd chapter-2/example-3
npm install
node src/index.js
如果我们忘记设置所需的环境变量,微服务会抛出一个错误!我们不应浪费时间去调试配置错误;错误日志将提供有用的信息,告诉我们如何解决问题:
Error: Please specify the port number for the HTTP server ➥ with the environment variable PORT.
at Object.<anonymous> (chapter-2\example-3\index.js:7:11)
现在我们需要在尝试再次运行代码之前设置 PORT 环境变量。在 Linux 和 macOS 上,我们使用以下命令设置它:
export PORT=3000
在 Windows 上,使用此命令:
set PORT=3000
再次启动微服务:
node src/index.js
这次应该能正确运行了。我们设置了 PORT 环境变量,所以微服务知道应该在哪个端口号上为 HTTP 服务器提供服务。为了测试,我们可以将浏览器指向
http://localhost:3000/video
。我们应该能像之前一样看到视频播放。
通过设置端口环境变量,我们可以在开发计算机上同时运行多个独立的微服务实例,只要它们使用不同的端口号。这在开发多个微服务时非常有用,因为我们可以轻松地为每个服务设置不同的端口。这种配置方式将在未来章节中重复使用,例如当我们添加数据库支持(第 4 章)和连接到消息队列服务器(第 5 章)时。
我们还可以使用环境变量来传递敏感数据给微服务,如数据库密码。我们应该谨慎处理这些信息,确保不将其存储在代码库中,以免泄露给不应该看到的人。在第 12 章中,我们将讨论如何管理敏感配置,如密码和 API 密钥。
2.6.7 设置生产环境
到目前为止,我们已经配置了在开发机上运行的微服务。这是必需的,因为我们需要在开发和测试过程中持续运行和检查它们。然而,在探讨更深入的内容之前(如 Docker、Kubernetes、Terraform 等),我们需要了解如何在生产环境中部署和运行我们的微服务。
提到生产环境,我指的是面向客户的环境,即托管我们应用程序,使其可供客户访问的环境。对于本书,我们的目标生产环境是 Kubernetes,我们将在 Kubernetes 集群中运行我们的应用程序,确保它们能被公众访问。
为了使现有的 Node.js 项目准备好在生产中运行,首先需要安装依赖项:
npm install
为生产环境准备微服务时,我们会稍微修改上面的命令:
npm install --omit=dev
这个命令通过 --omit=dev 参数省略开发依赖项,只安装生产所需的依赖项。
这一步很关键,因为在创建 Node.js 项目时,我们通常会有很多所谓的开发依赖项,这些依赖项仅支持我们的开发工作——我们不希望它们被安装到生产环境中。虽然你还没有见到开发依赖项的例子,但在下一节你会看到它们。
到目前为止,我们一直使用以下命令在开发计算机上运行我们的 HTTP 服务器:
node src/index.js
虽然这种方式没有问题,但现在我们开始使用 Node.js 的以下标准约定来运行我们的微服务:
npm start
使用 npm start 是启动 Node.js 应用程序的通用方法。这是 npm 脚本的一个特例,很快你将看到更多不同类型的 npm 脚本示例。在代码清单 2.6 (chapter-2/example-3/package.json) 中,我们已经更新了 package.json 文件,包括了一个 scripts 字段下的启动脚本,实质上就是用 Node.js 运行 index.js。
这里的好处是,无论我们处理哪个 Node.js 项目(只要遵循这个约定),我们都可以运行 npm start,而无需具体知道主文件是否被命名为 index.js,或者它是否有其他名称。我们也无需知道应用程序是否需要任何特殊的命令行参数或配置,因为这些细节都可以在这里定义。
这为我们提供了一个统一的命令,无论我们在查看哪个项目,无论特定应用程序的启动方式如何,我们都可以记住。这样做使得理解和运行任何 Node.js 项目变得更加简单,即使是那些由其他人创建的项目。
// 代码清单 2.6 向 package.json 添加启动脚本
{
"name": "example-1",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js" // 向 package.json 添加 npm start 脚本,让我们可以用“npm start”运行这个项目。
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^5.0.0-beta.1"
}
}
在代码清单 2.6 中,我们更新了 example-3 的 package.json 文件,以包含 npm start 脚本。你可以按照以下步骤试用它:
cd chapter-2/example-3
npm install
npm start
确保你首先运行 npm install 来获取依赖项,或者执行 npm install --omit=dev 如果你只想获取生产依赖项。
从现在开始在这本书中,我们将使用 npm start 来在生产环境中运行我们的每个微服务。将来,我将把这称为以生产模式运行我们的微服务。这是值得记住的一个命令,因为你将发现许多其他 Node.js 应用程序也遵循这一约定,这是一个有用的快捷方式,可以帮助你轻松运行其他开发者的代码。
刚刚介绍的命令足以使我们的微服务在生产环境中运行。这些命令也是我们将在第 3 章用来让微服务在 Docker 中运行的命令,所以我们很快将重新访问它们。
你可能也听说过 npm test 这个命令。这是用来运行 Node.js 项目的自动化测试的常规命令。我们将在第 9 章中回顾和探讨如何使用这个命令来测试我们的微服务。
2.6.8 实时重新加载以实现快速迭代
现在我们已经掌握了如何在生产环境中设置和运行微服务,同样重要的是在开发过程中有效地运行它。实时重新加载可以在我们修改代码后立即重启服务,这不仅加快了我们的开发节奏,还帮助我们实时获得反馈,无论是错误还是成功的输出。这样的即时反馈最大限度地减少了修改代码与测试结果之间的时间差。
我们将设置实时重新加载功能,如图 2.10 所示,这对于自动重启微服务非常重要,有助于我们进行快速的编码迭代和及时得到反馈。如我在 2.4 节中所述,迭代和快速反馈是我开发哲学的核心部分,实时重新加载也非常适合测试驱动开发,我们将在第 9 章中探讨这一点。

为了实现实时重新加载,我们将安装名为 nodemon 的工具。如图 2.10 所示,我们将使用 nodemon 来运行我们的微服务,它会自动监视项目中的代码变动。当检测到代码更改时,nodemon 会自动重启微服务,免去了我们手动重启的麻烦。
虽然这看起来是一个小优化,但在实际开发中,这种自动化能大大提高开发效率。它会让你有一种相见恨晚的感觉。你可以这样在 Node.js 项目中安装 nodemon:
npm install --save-dev nodemon
这里我们使用了 --save-dev 参数,将 nodemon 安装为开发依赖项,而不是生产依赖项。如前所述,这有助于我们确保只在开发环境中使用 nodemon,避免在生产环境中增加不必要的包。这是一个安全举措,尽管 nodemon 没有已知的安全问题,但通常来说,生产环境中安装的内容越少越好。这是我们在第 12 章讨论安全时会再次提及的主题。
因此,当我们运行 npm install --omit=dev 时,像 nodemon 这样的开发辅助包将被排除。通常,当我们需要运行 Node.js 代码时,我们会这样做:
node src/index.js
但现在,我们将使用 nodemon 代替 node 运行它:
npx nodemon src/index.js
这里出现的 npx 命令是 Node.js 提供的一个实用工具,允许我们直接从命令行运行项目中安装的包。这让我们可以使用正确的模块版本为每个项目运行工具,而不需要在全局环境中安装。
要停止在 nodemon 下运行的微服务,操作与在 Node.js 下相同。只需在终端中按 Ctrl-C 即可。
我通常喜欢在名为 start:dev 的 npm 脚本中使用 nodemon,这是我个人的约定,但你会发现许多其他开发者有类似的设置。你可以看到我们如何更新项目配置,将 nodemon 作为 devDependency 添加,并在 scripts 部分添加了新的 start:dev 脚本,如代码清单 2.7 (chapter-2/example-3/package.json) 所示。
// 代码清单 2.7 添加开发模式的启动脚本
{
"name": "example-3",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js", // 正常启动脚本,用于生产模式下的启动。
"start:dev": "nodemon src/index.js" // 新的 start:dev 脚本,用于开发模式下的启动。
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": { // 开发依赖项;这些依赖项不会安装在生产中。
"nodemon": "^2.0.18" // 我们刚刚添加的 nodemon 包的新依赖项
}
}
在上一节中,我介绍了 npm start 的使用。可以像这样在生产模式下运行我们的代码:
npm start
现在我们定义了 start:dev 命令,可以这样在开发模式下运行我们的微服务:
npm run start:dev
请注意使用 npm run 命令来执行我们添加到 package.json 文件中的自定义脚本。这提供了一种简便方式来集成构建脚本和其他实用脚本到我们的项目中。而对于特定的命令如 npm start 和 npm test(我们将在第 9 章详细讨论),我们可以省略 run 部分,因为 npm 对这些命令提供了特别的支持。
这意味着 start:dev 脚本并不是 Node.js 的一个标准约定,如 start 和 test 那样。因此我们需要使用 npm run 命令来执行它。在开发中使用 start:dev 是我的个人习惯,我们将在本书中继续使用它,你可能会发现在自己的开发工作中也很实用。
有了这些命令,我们可以根据需要在生产模式或开发模式下运行微服务,这样做可以确保我们根据不同模式的需求来适当配置和优化。
在开发模式下,我们的目标是优化快速迭代和开发速度。而在生产模式下,我们则更关注优化性能和安全性。这些目标往往互有冲突,因此需要分别对待。这种区分在我们接近微服务应用的生产部署时变得尤为重要,你将在第 6、7 和 8 章中看到这一点。
注意:在本书中介绍的所有微服务都遵循我们前两节中提到的约定。
2.6.9 运行本章的完整代码
如果到现在你还没有尝试过运行本章的代码,现在是个好时机。以下是一个快速指南,展示如何轻松地运行本章的示例。首先,获取第 2 章代码的本地副本,可以通过下载或从 GitHub 克隆第 2 章的仓库:
- 要运行流媒体视频示例,请尝试
example-2。 - 要查看使用环境变量配置微服务的示例,请尝试
example-3。
假设你想尝试 example-3。打开一个终端窗口,更改到相应的子目录:
cd chapter-2/example-3
接着安装依赖项:
npm install
如果你希望模拟生产环境的部署,可以使用:
npm install --omit=dev
要像在生产环境中一样运行它,请使用:
npm start
如果你想利用实时重新加载进行快速开发,请使用:
npm run start:dev
这些是运行本书中任何 Node.js 示例所需的主要命令。将本页加入书签,以便在需要时快速查看如何操作。
2.7 Node.js 回顾
在继续深入之前,让我们快速回顾一下本章中介绍的所有 Node.js 命令,如表 2.3 所示。
表 2.3 Node.js 命令回顾
| 命令 | 描述 |
|---|---|
node --version | 检查 Node.js 是否已安装并显示版本号 |
npm init -y | 快速创建一个新的 Node.js 项目,自动生成一个 package.json 文件 |
npm install --save <package-name> | 安装一个指定的 npm 包,并将其添加到项目依赖中 |
npm install | 安装 package.json 中列出的所有项目依赖项 |
node <script-file> | 执行一个 Node.js 脚本文件,文件名可以是 main.js、server.js 或保持约定的 index.js |
npm start | 使用 package.json 中定义的 start 脚本启动 Node.js 应用 |
npm run start:dev | 运行一个为开发环境定制的启动脚本,通常用于启动实时重新加载服务 |
2.8 继续学习
若想深入了解 Node.js 和 Express,以下是一些推荐阅读资源:
- 《Get Programming with Node.js》,Jonathan Wexler 著(Manning, 2019)
- 《Node.js in Action》第二版,由 Alex R. Young、Bradley Meck 和 Mike Cantelon 共同著(Manning,2017)
- 《Git in Action》,Mike McQuaid 著(Manning,2014)
你还可以访问 https://nodejs.org/en/docs/ 获取更多信息。
接下来,我们将学习如何包装和发布我们的微服务,使其可以部署到云平台上。为此,我们将使用 Docker,这是一个行业内无处不在且至关重要的工具。Docker 简化了微服务的访问,并彻底改变了我们构建和部署软件的方式。
总结
- 本项目的开发理念是迭代、保持运行状态和从简单做起。
- 创建并处理单个微服务需要在本地开发机上配置一个开发环境。
- 我们需要一个编辑器,如 VS Code,来编写和编辑代码。
- 使用 Git 克隆示例代码库,同时在日常工作中使用 Git 管理代码变更。
- Node.js 设计之初就是为了方便开发面向网络的分布式应用,这使得创建单个微服务变得非常简单。
- 使用 JavaScript 可以方便地进行全栈编程,轻松在应用的后端和前端之间切换。
- Express.js 是 Node.js 上事实上的标准网络服务器框架,它使我们的微服务能够处理来自网络的 HTTP 请求。
- 视频流是我们第一个微服务的简单示例,也是 FlixTube 应用的核心功能。
- 我们的第一个微服务可以在开发模式或生产模式下运行,这非常重要,因为这些模式有不同的需求。
- 使用 nodemon 运行我们的微服务可以在开发过程中实现实时重新加载,提供快速反馈,帮助创建快速的开发节奏。
- 环境变量是本书中介绍的微服务配置方法。