利用NestJS构建可扩展微服务
立即解锁
发布时间: 2025-08-14 01:10:35 阅读量: 3 订阅数: 13 


NestJS可扩展应用开发实战
### 利用 NestJS 构建可扩展微服务
#### 1. NestJS 微服务包概述
NestJS 的 `@nestjs/microservices` 包具有以下核心优势:
- **弹性通信**:内置处理服务中断的策略,如重试和退避机制,确保服务在故障条件下保持健壮。
- **与其他模块集成**:该包旨在与其他 NestJS 模块和谐协作,保证安全和配置等方面在所有服务中得到一致管理。
下面通过一个简单示例展示如何使用该模块实现微服务间的通信。假设我们有一个服务需要异步处理用户数据:
```typescript
import { Controller } from '@nestjs/common';
import {
MessagePattern,
Payload
} from '@nestjs/microservices';
@Controller()
export class UserDataProcessor {
@MessagePattern({ cmd: 'process_user_data'})
async processUserData(@Payload() data: any) {
// Logic to process user data
console.log('Processing user data:', data);
}
}
```
在这个示例中,`@MessagePattern` 装饰器修饰 `processUserData` 方法,用于监听 `{ cmd: 'process_user_data'}` 模式的消息。每当接收到该主题的消息时,该方法将被触发,并携带消息负载。
#### 2. 搭建单仓库结构
在深入微服务通信之前,我们需要将当前项目结构转换为单仓库(mono repo)结构。步骤如下:
1. 使用 `nest-cli` 生成多个应用。在项目根目录运行以下命令:
```bash
$ nest generate app order
# then
$ nest generate app inventory
```
2. 运行上述命令后,项目结构会发生如下变化:
- 项目根目录下新增 `apps/` 文件夹。
- 现有项目位于 `/apps/original-application-name` 下(这里 `original-application-name` 为 `microservices-sample`)。
- `package.json` 文件中的部分命令更新,例如 `start:prod` 命令变为 `"start:prod": "node dist/apps/microservices-sample/main"`,这意味着 `microservices-sample` 项目将作为入口点,即 API 网关。
- `nest-cli.json` 文件更新如下:
```json
{
"$schema":
"<https://json.schemastore.org/nest-cli>",
"collection": "@nestjs/schematics",
"sourceRoot": "apps/microservices-sample/src",
"compilerOptions": {
"deleteOutDir": true,
"webpack": true,
"tsConfigPath":
"apps/microservices-sample/tsconfig.app.json"
},
"monorepo": true,
"root": "apps/microservices-sample",
"projects": {
"microservices-sample": {
"type": "application",
"root": "apps/microservices-sample",
"entryFile": "main",
"sourceRoot": "apps/microservices-sample/src",
"compilerOptions": {
"tsConfigPath": "apps/microservices-sample/tsconfig.app.json"
}
},
"order": {
"type": "application",
"root": "apps/order",
"entryFile": "main",
"sourceRoot": "apps/order/src",
"compilerOptions": {
"tsConfigPath": "apps/order/tsconfig.app.json"
}
},
"inventory": {
"type": "application",
"root": "apps/inventory",
"entryFile": "main",
"sourceRoot": "apps/inventory/src",
"compilerOptions": {
"tsConfigPath":
"apps/inventory/tsconfig.app.json"
}
}
}
}
```
#### 3. 应用关键特性
为了简化操作,我们将构建一个简单的订单管理系统,其核心功能如下:
| 步骤 | 描述 |
| ---- | ---- |
| 1 | 当用户下单时,向订单服务发送包含订单信息(如购买用户、产品、总价)的 POST 请求。 |
| 2 | 订单服务接收到请求后,发起订单创建操作(可视为数据库事务),并发出 `order_created` 主题的事件,该事件将由库存服务消费。 |
| 3 | 库存服务接收到 `order_created` 事件后,检查库存中是否有足够的产品。如果有,通过 `order_processed` 主题的事件更新库存水平和订单状态;如果没有,则通过相同主题但不同负载的事件拒绝订单创建,订单服务将相应更新订单状态。 |
#### 4. 构建订单服务
##### 4.1 订单服务技术要求
- 监听 `/orders` 端点的 HTTP POST 请求以创建新订单。
- 订单创建后发出事件,由库存服务处理。
- 监听来自库存服务的事件,并相应更新订单状态。
##### 4.2 实现订单服务逻辑
1. 更新 `apps/order/src/main.ts` 文件:
```typescript
import { NestFactory } from '@nestjs/core';
import { OrderModule } from './order.module';
async function bootstrap() {
const app = await NestFactory.create(OrderModule);
// to connect to the microservices linked to the order
// service
app.startAllMicroservices();
await app.listen(3001);
}
bootstrap();
```
2. 创建 `apps/order/entities/order.entity.ts` 文件,定义订单实体:
```typescript
export enum OrderStatus {
PENDING = 'Pending',
COMPLETED = 'Completed',
CANCELLED = 'Cancelled',
}
export class Order {
id: string;
name: string;
product: string;
price: number;
status: OrderStatus;
quantity: number;
}
```
3. 在 `OrderModule` 中注册库存服务:
```typescript
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { OrderController } from './order.controller';
import { OrderService } from './order.service';
@Module({
imports: [
ClientsModule.register([
{
name: 'INVENTORY_SERVICE',
transport: Transport.TCP,
options: {
port: 8002,
},
},
]),
],
controllers: [OrderController],
providers: [OrderService],
})
export class OrderModule {}
```
4. 实现订单创建业务逻辑:
```typescript
// order/order.service.ts
import { Inject, Injectable } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { Order, OrderStatus } from './entities/order.entity';
import { CreateOrderInput } from './dto/create-order.dto';
@Injectable()
export class OrderService {
constructor(
@Inject('INVENTORY_SERVICE') private inventoryClient: ClientProxy,
) {}
// in memory storage - for demo purposes
private orders: Order[] = [];
createOrder(createOrderInput: CreateOrderInput): Order {
const order = {
```
0
0
复制全文
相关推荐









