likes
comments
collection
share

NestJS小技巧10-使用Nest.JS在Node中实现可扩展的微服务

作者站长头像
站长
· 阅读数 17
by 雪隐 from https://juejin.cn/user/1433418895994094
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可联系授权

原文链接

嗨,伙计们,祝大家一切顺利,今天我想和你们分享一些我们已经做了一段时间的事情,并学到了很多关于将清洁架构应用于我们的微服务的知识。

在进入代码之前,让我们了解微服务是如何工作和组织我们的代码的,从而使服务越来越独立于框架,易于测试,无论用户界面如何,也就是说,用户界面可以随意更改,而不会反映在应用程序的其他部分,是独立于数据库的,因为它维护应用程序本身的所有业务规则,最后,独立于任何外部代理,因为业务规则不会“看到”“外部世界”。

什么是微服务?

微服务是一种架构,旨在隔离给定系统的每个功能,将它们转换为具有独立部署可能性的松散耦合服务。

微服务体系结构作为一种用于单片web应用程序的解决方案而出现。在单片应用程序中,一切都是内置单元,整个业务规则被定义并分组为一个综合应用程序,在微服务架构中更新代码库可能会变得相当复杂,因为它会影响整个系统,即使是最小的更改也可能是构建和部署新版本系统所必需的。

我们现在知道,微服务通过将应用程序模块(功能)分离成更小的部分来解决单片系统的问题。

NestJS小技巧10-使用Nest.JS在Node中实现可扩展的微服务

我们应该在什么时候使用微服务架构?

这两种架构都有其优缺点,尽管微服务架构将解决加速复杂系统开发的问题,但何时使用它们还没有明确的答案。通过微服务和解耦,开发人员最终获得了灵活性,否则单块架构是不可能实现的。

单片应用程序最终很难扩展,因为每个应用程序都需要复制,如果一个应用程序完全依赖于一个数据库,这将更加困难。另一方面,微服务可以根据单个服务进行扩展或复制。如果你需要发送更多的电子邮件,只需扩展负责电子邮件功能的微服务即可。

如果您需要实现微服务架构,请问以下问题:我的单片应用程序有问题吗?如果您有任何问题,您可能需要考虑切换到微服务。如果没有,那就坚持下去 —— 没有必要投入时间来解决一个不存在的问题。

微服务的缺点

微服务体系结构并不是解决所有问题的神奇解决方案,它也有缺点。其中一些缺点是:

  • 由于不同的服务使用不同的数据库,因此涉及多个服务的事务需要使用最终的一致性
  • 完美的服务划分在第一次尝试时很难实现,在达到尽可能好的服务分离之前需要反复进行。
  • 当服务通过使用网络交互进行通信时,由于网络延迟和服务速度慢,这会降低应用程序的速度。

为什么NestJs用于微服务?

创建微服务时,有几种主要的编程语言从健壮的框架中进行选择。NestJs为我们提供了许多工具来创建一个健壮、有组织、可测试的应用程序。一个亮点是框架带来的依赖注入功能,我们可以将一个模块注入另一个模块,从而促进代码重用。但值得注意的是,当这种依赖注入使模块相互依赖时,我们会损害一些清洁架构的概念。

我们接下来要创建的项目来尝试开发API,该API能够保持其输入接口、响应和业务规则高度独立于数据库和框架。

创建我们的微服务

我们将开始创建我们的微服务,考虑它可以解决的问题,以便更容易地定义我们将要使用的功能。我们将实现的通信协议是TCP,我们将使用PacketSender进行测试,这是一个开源应用程序,允许我们发送支持TCP的网络数据包。

## MacOS 安装 packetsender
brew install packetsender

通过HTTP实现微服务与使用Node.JS实现API没有什么不同,因为微服务有一个定义明确的架构和范围,所以我们会选择使用TCP数据包的异步模式,我们将与微服务通信,因此选择Nest.JS,因为它有许多内置功能,使我们更容易创建微服务架构。

我们将把开发分为四个阶段,这样本教程就不会过于宽泛,它们是:

  • 微服务结构和配置
  • 创建与微服务通信的消息模式
  • 使用PacketSender执行微服务测试
  • 我们把这一步作为锦上添花,最后我会在下一章告诉你下一步是什么😄

微服务结构和配置

在这一步中,我们将使用以下命令使用CLI在NestJS中创建一个新的应用程序

npx @nestjs/cli new products-microservice

既然你的应用程序已经创建好了,请确保你处于项目的根位置,并安装一个库@nestjs/micservices

cd products-microservice && pnpm i @nestjs/microservices

我们需要修改main.ts,将其保留为下面的代码片段:

import { INestMicroservice } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { Transport } from '@nestjs/microservices';
import { AppModule } from './app.module';

// 创建微服务options对象
const microserviceOptions = {
  transport: Transport.TCP,
  options: {
    host: process.env.HOST, //
    port: process.env.PORT,
  },
};

(async () => {
  const app: INestMicroservice = await NestFactory.createMicroservice(
    AppModule,
    microserviceOptions,
  );
  
  await app.listen();

  console.info('Microservice is listening...', process.env.PORT || 8080);

})();

NestJS支持几种内置的传输层实现。上面的代码将创建一个微服务,该服务通过TCP传输层与端口8080进行通信。


我们可以选择使用消息模式或事件模式与微服务进行通信。

消息模式充当一种请求-响应方法,他在服务和事件模式之间交换消息,以便在不等待响应的情况下发布事件。

我们将只实现基于给定输入创建产品的功能,然后我们将获得创建的产品。因此,让我们在app.controller.ts文件中注册一个命名的消息模式create_product

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @MessagePattern('create_product')
  async createProduct(@Payload() payload: CreateProductDto) {
    const product = await this.appService.createProduct(payload);
    return product;
  }
}

接下来,我们将抽象创建新产品的逻辑,它可以根据需求和使用的数据库以不同的方式实现,并且我们将只关注与微服务相关的需求。

我们用于创建新产品的有效载荷将如下所示:

import { IsString, IsEmail, IsNotEmpty } from 'class-validator';

export class CreateProductDto {
  @IsNotEmpty()
  @IsEmail()
  name: string;
 
  @IsNotEmpty()
  @IsNumber()
  price: number;
}

最后,最重要的是我们的服务,它将负责将这些数据保存在库中。

...
import Product from '../entity/product.entity';
import { CreateProductDto } from '../dto/create-product.dto';
...

@Injectable()
export default class AppService {

  constructor(
    @InjectRepository(Product) private readonly productRepository: Repository<Product>,
  ){}
  
  async createProduct(body: Partial<Product>): Promise<UserDto> {
    try {
     	const product = new Product();
	product.name = body.name;
	product.price = body.price;
      
      	const productCreated = await this.productRepository.save(product);
      
      	return productCreated;

    } catch (e) {
	throw new InternalServerErrorException('Error');
    }
  }
...
}

创建所有代码后,我们可以使用PackatSender在应用程序中执行测试。

使用PacketSender执行微服务测试

现在我们已经配置和结构化了微服务,我们需要执行测试来检查是否一切正常,为此我们将使用PacketSender向我们的应用程序发送TCP数据包。将地址端口设置为127.0.0.1:8080,然后从右侧的下拉菜单中选择TCP。要对我们的消息进行编码,请使用ASCII字段并用以下值填充:

112#{"pattern":"create_product", "data":{"name":"G Suite","price":120}, "id":"ce51ebd3-32b1-4ae6-b7ef-e018126c4cc4"}
  • pattern-是我们在微服务create_product中定义的消息,;
  • data-是我们想要发送的JSON对象,一个有nameprice的对象;

112表示我们的消息从第一个键开始到最后一个键的长度(两者都包括在内)。

NestJS小技巧10-使用Nest.JS在Node中实现可扩展的微服务

参照

结论

NestJS提供了构建轻量级、结构良好、令人惊叹的微服务的可能性。开箱即用的工具和功能使开发、扩展和维护变得美观高效。

本章代码

代码