NestJS小技巧10-使用Nest.JS在Node中实现可扩展的微服务
by 雪隐 from https://juejin.cn/user/1433418895994094
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可联系授权
嗨,伙计们,祝大家一切顺利,今天我想和你们分享一些我们已经做了一段时间的事情,并学到了很多关于将清洁架构应用于我们的微服务的知识。
在进入代码之前,让我们了解微服务是如何工作和组织我们的代码的,从而使服务越来越独立于框架,易于测试,无论用户界面如何,也就是说,用户界面可以随意更改,而不会反映在应用程序的其他部分,是独立于数据库的,因为它维护应用程序本身的所有业务规则,最后,独立于任何外部代理,因为业务规则不会“看到”“外部世界”。
什么是微服务?
微服务是一种架构,旨在隔离给定系统的每个功能,将它们转换为具有独立部署可能性的松散耦合服务。
微服务体系结构作为一种用于单片web应用程序的解决方案而出现。在单片应用程序中,一切都是内置单元,整个业务规则被定义并分组为一个综合应用程序,在微服务架构中更新代码库可能会变得相当复杂,因为它会影响整个系统,即使是最小的更改也可能是构建和部署新版本系统所必需的。
我们现在知道,微服务通过将应用程序模块(功能)分离成更小的部分来解决单片系统的问题。
我们应该在什么时候使用微服务架构?
这两种架构都有其优缺点,尽管微服务架构将解决加速复杂系统开发的问题,但何时使用它们还没有明确的答案。通过微服务和解耦,开发人员最终获得了灵活性,否则单块架构是不可能实现的。
单片应用程序最终很难扩展,因为每个应用程序都需要复制,如果一个应用程序完全依赖于一个数据库,这将更加困难。另一方面,微服务可以根据单个服务进行扩展或复制。如果你需要发送更多的电子邮件,只需扩展负责电子邮件功能的微服务即可。
如果您需要实现微服务架构,请问以下问题:我的单片应用程序有问题吗?如果您有任何问题,您可能需要考虑切换到微服务。如果没有,那就坚持下去 —— 没有必要投入时间来解决一个不存在的问题。
微服务的缺点
微服务体系结构并不是解决所有问题的神奇解决方案,它也有缺点。其中一些缺点是:
- 由于不同的服务使用不同的数据库,因此涉及多个服务的事务需要使用最终的一致性。
- 完美的服务划分在第一次尝试时很难实现,在达到尽可能好的服务分离之前需要反复进行。
- 当服务通过使用网络交互进行通信时,由于网络延迟和服务速度慢,这会降低应用程序的速度。
为什么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对象,一个有name
和price
的对象;
值112
表示我们的消息从第一个键开始到最后一个键的长度(两者都包括在内)。
参照
- NestJS微服务官方文档: docs.nestjs.com/microservic…
结论
NestJS提供了构建轻量级、结构良好、令人惊叹的微服务的可能性。开箱即用的工具和功能使开发、扩展和维护变得美观高效。
本章代码
转载自:https://juejin.cn/post/7219124460804145209