TypeScript
今天,我想向你介绍在 NestJS(TypeScript) 中结合 Google 的 gRPC 框架 和 API 网关 处理传入的 HTTP 请求以及基于 JWT 的 身份验证 的 微服务。由于本文内容较长,因此我将其分为两部分。
- 介绍、准备工作、数据库、共享 Proto 项目
- 身份验证微服务、产品微服务、订单微服务 你将在每个部分的链接中找到每个存储库的链接。你可以在这里阅读第二部分。
应用基础架构
为本文,我决定编写一个简单的电子商务微服务项目,其中包含一个 API 网关,用于管理传入的 HTTP 请求并将其转发到总共三个微服务中。
- 第一个服务将是身份验证,用户可以在其中注册和登录,同时我们验证请求的授权。
- 第二个服务将处理产品,以创建新产品,但也可以根据其 ID 查找产品。
- 这对于处理我们小型电子商务应用程序的传入订单的第三个服务非常重要。
你会发现,每个服务都尽可能的最小,以介绍 NestJS 和 TypeScript 中的微服务基础知识,同时不会使我们的应用程序变得复杂。
我们不会处理环境变量、截止时间、深度错误处理、Docker 和复杂的配置。所以不用担心,我们会保持简单!
每个服务都将是一个独立的项目,所以请记住这一点。此外,我们将拥有一个共享的存储库,其中存储和管理 Proto 文件,这是在使用 gRPC 时的常规做法。最后但并非最不重要的是,我们将创建另一个项目,这将是 API 网关。因此,总共有五个项目。
在我们开始这个指南之前,让我们简要谈谈我们将使用的框架和概念。这可能听起来很无聊,但请跟着我走,了解发生了什么,以便跟随并理解我们要构建的应用程序。
什么是 NestJS?
NestJS 是一个用于构建高效、可扩展的 Node.js Web 应用程序的框架。它使用现代 JavaScript,并使用 TypeScript 构建。如果你使用 TypeScript 构建 API,则 NestJS 是最好的选择!它受到 Spring 和 Angular 的强烈启发。
什么是 gRPC?
gRPC 是一个现代的、开源的、高性能的 RPC 框架,可以在任何环境中运行。它可以高效地连接数据中心内部和跨数据中心的服务,并提供可插拔的支持负载平衡、跟踪、健康检查和身份验证。
什么是 API 网关?
API 网关是所有客户端的入口点,即基于 HTTP 的所有客户端请求,但它不仅限于 HTTP。API 网关有两种处理请求的方式。一些请求只是代理/路由到适当的服务。它通过扇出到多个服务来处理其他请求。
照片来自 Maxime Horlaville 在 Unsplash
逐步指南
正如我所说,我将本文分为 两部分。涵盖范围如下:
- 数据库、共享 Proto 项目、API 网关
- 身份验证微服务、产品微服务和订单微服务
先决条件
需要具有 TypeScript、RPC、Git(+Github)、在本地安装的 PostgreSQL 的基本了解。我将选择 Visual Studio Code 作为我的代码编辑器。你可以使用你喜欢的任何编辑器。
注意
你会经常看到本文中的 code .
命令。这是一个 Visual Studio Code 命令,它基于当前目录打开 Visual Studio Code。如果你不使用 Visual Studio Code,请确保在你的 IDE 或代码编辑器中打开正确的目录。
数据库
首先,我们需要创建 3 个 PostgreSQL 数据库。这是因为我们将遵循 每个服务的数据库 模式。每个微服务都将有自己的数据库,以实现数据管理的独立性。
每个人都有不同的处理方式,有些人使用某种 GUI,但我们将使用终端。同样,你需要在本地安装 PostgreSQL。如果你已经安装了 PostgreSQL,则以下四个命令将在 Linux、Mac 和 Windows 机器上运行。
$ psql postgres
$ CREATE DATABASE micro_auth;
$ CREATE DATABASE micro_product;
$ CREATE DATABASE micro_order;
$ \l
$ \q
命令解释:
psql postgres
打开带有用户 Postgres 的 psql CLICREATE DATABASE micro_auth;
创建数据库CREATE DATABASE micro_product;
创建数据库CREATE DATABASE micro_order;
创建数据库\l
列出所有数据库\q
退出 psql CLI
我们成功执行所有四个命令后,我的终端将如下所示。我们可以看到,成功创建了 3 个数据库。
创建项目
让我们继续使用 NestJS。我们将全局安装 NestJS CLI。
$ npm i -g @nestjs/cli
我们使用其 CLI 初始化 4 个新的 NestJS 项目。此外,我们创建一个项目,用于共享通过 Github 的 proto 文件。
我建议在你的终端中创建一个工作区文件夹,以在其中执行以下命令,以便将所有项目放在一个地方,但这取决于你。因此,它不是本指南的一部分。
$ mkdir grpc-nest-proto
$ nest new grpc-nest-api-gateway -p npm
$ nest new grpc-nest-auth-svc -p npm
$ nest new grpc-nest-product-svc -p npm
$ nest new grpc-nest-order-svc -p npm
```# 共享Proto仓库
正如我所说,我们将从共享Proto项目开始。我们需要这样做是因为我们必须在所有其他项目中使用这些文件。
Github: [https://github.com/hellokvn/grpc-nest-proto](https://github.com/hellokvn/grpc-nest-proto)
首先,我们需要在代码编辑器中打开项目,这个命令`code .`会在我们的VSCode编辑器中打开`grpc-proto`项目。
$ cd grpc-nest-proto $ npm init --y $ git init $ mkdir proto $ touch proto/auth.proto && touch proto/product.proto && touch proto/order.proto $ code .
项目将看起来像这样:

然后,我们将在Proto文件中添加一些代码。跟着我来。
## 认证Proto
首先,我们将为我们的身份验证服务创建Proto文件。我们将添加3个RPC端点:`Register`,`Login`和`Validate`
让我们在`proto/auth.proto`中添加一些代码
## 订单Proto
其次,我们将为我们的订单服务创建Proto文件。我们只会添加1个RPC端点,称为`CreateOrder`。
让我们在`proto/order.proto`中添加一些代码
## 产品Proto
最后但并非最不重要的,我们将为我们的产品服务创建Proto文件。我们将添加3个RPC端点:`CreateProduct`,`FineOne`和`DecreaseStock`
让我们在`proto/product.proto`中添加一些代码
## 在Github上创建仓库
正如我所说,我们需要以某种方式分享此项目。对于本指南,我选择了Github。因此,让我们在[此处](https://github.com/new)创建一个公共仓库。顺便说一句,这是本教程中你需要创建的唯一存储库。稍后,我们将在我们的项目中安装此存储库作为NPM包。

让我们回到我们的代码,因为我们需要提交和推送我们的项目。
> <p data-selectable-paragraph=""><em>将</em><em> YOUR_USERNAME </em><em>替换为你的Github用户名。</em></p>
$ git remote add origin https://github.com/YOUR_USERNAME/grpc-nest-proto.git $ git add . $ git commit -m "chore(): init nestjs" $ git branch -M main $ git push -u origin main
这就是全部内容。现在我们的代码应该在Github上。我们不会再在这里做任何更改,让我们继续前进到API网关。
# API网关
存储库:[https://github.com/hellokvn/grpc-nest-api-gateway](https://github.com/hellokvn/grpc-nest-api-gateway)
在此项目中,我们将转发我们的HTTP请求到我们的微服务。有时需要对传入请求进行授权,这部分是与我们稍后要编写的Auth服务结合使用的部分。
首先,我们需要在代码编辑器中打开项目,因此返回到终端内部,进入我们存储项目的目录。
$ cd grpc-nest-api-gateway $ code .
## 安装依赖项
让我们安装一些我们需要的依赖项。
$ npm i @nestjs/microservices @grpc/grpc-js @grpc/proto-loader $ npm i -D @types/node ts-proto
## 项目结构
通常在我的指南中,我将继续创建最终的文件夹和文件结构。为简单起见,我们只在这里使用一个单一模块。
$ nest g mo auth && nest g co auth --no-spec && nest g s auth --no-spec $ nest g mo product && nest g co product --no-spec $ nest g mo order && nest g co order --no-spec $ touch src/auth/auth.guard.ts
## 添加脚本
我们需要向我们的`package.json`添加一些脚本,以根据我们刚刚完成的共享Proto项目生成我们的protobuf文件。
让我们只需在`package.json`文件的`scripts`属性中添加这5行代码。
> <p data-selectable-paragraph=""><em>将</em><em> YOUR_USERNAME </em><em>替换为你的Github用户名。</em></p>
package.json
这是我的`package.json`将如何显示或者可以查看[我的存储库](https://github.com/hellokvn/grpc-nest-api-gateway/blob/main/package.json)中的此文件。

让我们运行这些脚本!
$ npm run proto:install && npm run proto:all
- `proto:install`将我们的共享Proto存储库安装为NPM包
- `proto:all`将在我们的模块`auth`,`order`和`product`中生成后缀为`.pb.ts`的protobuf文件
因此,在这些步骤之后,该项目应如下所示:

现在,让我们开始编码。
## AuthService
因此,在这里我们要让我们的身份验证服务调用其稍后要编写的验证方法。但是,我们已经可以准备好了,因为我们有它的protobuf文件。我们知道它的响应和有效负载。
让我们从`src/auth/auth.service.ts`更改为:
## Auth Guard
我们的AuthGuard取决于我们刚刚创建的服务。在这里,我们获取我们稍后要获取的Bearer Token。然后,我们验证此令牌,如果无效,则抛出未经授权的异常,因此我们会阻止没有有效授权的用户的请求。
让我们从`src/auth/auth.guard.ts`更改为:
## Auth Controller
Auth微服务还将负责新用户和用户登录,因此我们还将在API网关中添加控制器,以将这些请求转发到我们的身份验证微服务。
让我们从`src/auth/auth.controller.ts`更改为:
## Auth Module
现在,我们需要注册我们的身份验证服务。我们需要使此模块全局,并导出我们的AuthService,因为我们需要在其他模块中使用依赖于AuthService的AuthGuard。因此请记住这一点。
让我们从`src/auth/auth.module.ts`文件更改为:
现在,我们已经完成了API Gateway的身份验证模块。让我们继续进行订单模块。它比我们的身份验证模块简单得多。## 订单模块
与我们的AuthModule类似,我们需要注册我们的Order Microservice以便以后与它通信。
也许你会意识到,我们将使用与Authentication Service不同的端口,这是必要的,因为我们不能两次使用同一个端口。
让我们从以下内容更改`src/order/order.module.ts`:
到
## 订单控制器
在这里,我们只需要编写1个端点,因为我们的Order Microservice只拥有1个端点。看一下,我们将在这里使用我们的AuthGuard服务,来验证我们现在要编写的POST请求的授权。
如果发出此请求的用户已经被授权,AuthGuard会将用户的ID添加到请求中,我们将在此处将其与请求体合并,因为我们的protobuf文件`order.pb.ts`需要一个用户ID。
让我们从以下内容更改`src/order/order.controller.ts`:
到
## 产品模块
现在让我们为我们的API Gateway的Product模块重复这个过程。
让我们从以下内容更改`src/product/product.module.ts`:
到
## 产品控制器
Product Microservice包含3个端点,但DecreaseStock不应该从我们的API Gateway中可达,这就是为什么我们只添加另外2个端点的原因。
让我们从以下内容更改`src/product/product.controller.ts`:
太棒了!完成了API Gateway。现在我们可以运行它了。不幸的是,没有微服务的API Gateway是无用的,因此让我们继续本文的第二部分。
$ npm run start:dev

译自:https://levelup.gitconnected.com/nestjs-microservices-with-grpc-api-gateway-and-authentication-part-1-2-650009c03686
评论(0)