在 Nest 中,微服务本质上是一个使用与 HTTP 不同的传输层的应用。
Nest 支持多种内置的传输层实现,称为传输器,它们负责在不同的微服务实例之间传输消息。大多数传输器本身支持请求-响应和基于事件的消息样式。Nest 将每个传输器的实现细节抽象为请求-响应和基于事件的消息传递的规范接口。
1. 创建项目
使用 cli 创建项目
nest new bookstore
2. 创建微服务
进入目录后,使用 cli 创建微服务
nest g app warehouse
生成后的目录
安装微服务和配置的依赖包
pnpm i @nestjs/microservices
pnpm i @nestjs/config
创建 .env 文件,配置微服务的 host 和 port
BOOKSTORE_SERVICE_HOST=127.0.0.1
BOOKSTORE_SERVICE_PORT=3001
3. 设置微服务
3.1 修改 warehouse 模块
修改 apps/warehouse/warehouse.module.ts 文件,把config模块引入
import { Module } from '@nestjs/common';
import { WarehouseController } from './warehouse.controller';
import { WarehouseService } from './warehouse.service';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [ConfigModule.forRoot()],
controllers: [WarehouseController],
providers: [WarehouseService],
})
export class WarehouseModule {}
3.2 修改 warehouse 主文件
修改 apps/warehouse/main.ts 文件,先创建app上下文,获取到config的配置中微服务的 host 和port 值。使用 createMicroservice 创建微服务,设置TCP传输和参数
import { NestFactory } from '@nestjs/core';
import { WarehouseModule } from './warehouse.module';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { ConfigService } from '@nestjs/config';
async function bootstrap() {
const appContext = await NestFactory.createApplicationContext(
WarehouseModule,
);
const configService = appContext.get(ConfigService);
const host = configService.get<string>('BOOKSTORE_SERVICE_HOST');
const port = configService.get<number>('BOOKSTORE_SERVICE_PORT');
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
WarehouseModule,
{
transport: Transport.TCP,
options: {
host: host,
port: port,
},
},
);
await app.listen();
}
bootstrap();
3.3 修改 warehouse 控制器
增加 newBook 添加图书, getBook 通过ID查询图书, getBooks 查询所有图书,3个方法
并使用 MessagePattern 装饰器,启用请求-响应消息类型
import { Controller } from '@nestjs/common';
import { WarehouseService } from './warehouse.service';
import { MessagePattern } from '@nestjs/microservices';
import { bookDto } from 'dto/book.dto';
@Controller()
export class WarehouseController {
constructor(private readonly warehouseService: WarehouseService) {}
@MessagePattern({ cmd: 'add_book' })
addBook(book: bookDto) {
return this.warehouseService.addBook(book);
}
@MessagePattern({ cmd: 'get_book' })
getBook(id: string) {
return this.warehouseService.getBook(id);
}
@MessagePattern({ cmd: 'get_books' })
getBooks() {
return this.warehouseService.getAllBooks();
}
}
补充一个 book.dto.ts 文件
export class bookDto {
id: string;
title: string;
author: string;
release_date: string;
}
3.4 修改 warehouse 服务
import { Injectable } from '@nestjs/common';
import { bookDto } from 'dto/book.dto';
const bookStore: bookDto[] = [];
@Injectable()
export class WarehouseService {
addBook(book: bookDto) {
book.id = bookStore.length + 1 + '';
bookStore.push(book);
return book;
}
getBook(id: string) {
return bookStore.find((book: bookDto) => book.id === id);
}
getAllBooks() {
return bookStore;
}
}
4. 设置主服务
4.1 修改 bookstore 模块
添加 config 模块和微服务的 provide
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { ClientProxyFactory, Transport } from '@nestjs/microservices';
@Module({
imports: [ConfigModule.forRoot()],
controllers: [AppController],
providers: [
AppService,
{
provide: 'WAREHOUSE_SERVICE',
inject: [ConfigService],
useFactory: (configService: ConfigService) => {
return ClientProxyFactory.create({
transport: Transport.TCP,
options: {
host: configService.get('BOOKSTORE_SERVICE_HOST'),
port: configService.get('BOOKSTORE_SERVICE_PORT'),
},
});
},
},
],
})
export class AppModule {}
4.2 修改 bookstore 控制器
注入微服务的service,并增加3个方法
getAllBooks 查询所有图书
getBookById 通过ID查询图书
addBook 添加图书
import { Body, Controller, Get, Inject, Param, Post } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { bookDto } from 'dto/book.dto';
import { Observable } from 'rxjs';
@Controller('bookstore')
export class AppController {
constructor(
@Inject('WAREHOUSE_SERVICE') private warehouseService: ClientProxy,
) {}
@Get()
getAllBooks(): Observable<bookDto[]> {
return this.warehouseService.send({ cmd: 'get_books' }, {});
}
@Get(':id')
getBookById(@Param('id') id: string): Observable<bookDto | undefined> {
return this.warehouseService.send({ cmd: 'get_book' }, id);
}
@Post()
addBook(@Body() book: bookDto): Observable<bookDto> {
return this.warehouseService.send({ cmd: 'add_book' }, book);
}
}
5. 启动服务
启动微服务
nest start warehouse --watch
启动主服务
nest start bookstore --watch