首先安装nestjs并创建三个nestjs项目,一个主服务(main-service),两个子服务(microservice1,microservice2)
所有服务均推荐使用pnpm进行安装,方便后面配置共享依赖
npm i -g @nestjs/cli // 安装nestjs脚手架(如果没有安装过的话)
mkdir nest-cloud // 创建一个文件夹用于存放所有服务
cd mkdir
nest new main-service // 主服务
mkdir children-service // 创建子服务项目用于存放所有子服务
cd children-service
nest new microservice1 // 子服务1
nest new microservice2 // 子服务2
// 最后cd到每一个服务下面安装@nestjs/microservices依赖,这样做感觉很麻烦,最后再讲解决方案
pnpm i @nestjs/microservices -S
现在需要配置两个字服务与主服务以tcp协议进行通讯,如果对微服务概念不熟悉的可自行百度
// 这是子服务1的main.ts
import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.TCP,
options:{
port:3001,
}
},
);
app.listen();
console.log(3001,'子服务已启动');
}
bootstrap();
// 这是子服务2的main.ts
import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.TCP,
options:{
port:3002,
}
},
);
app.listen();
console.log(3002,'子服务已启动');
}
bootstrap();
然后在主服务中注册两个子服务
// 主服务的app.module.ts
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ClientsModule.register([
{
name: 'microservice1',
transport: Transport.TCP,
options: {
port: 3001,
},
},
]),
ClientsModule.register([
{
name: 'microservice2',
transport: Transport.TCP,
options: {
port: 3002,
},
},
])
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
配置完成,现在子服务的3001,3002的接口时没有办法直接进行访问的,必须在3000主服务上进行分发
我在主服务的 app.controller.ts 定义了三个接口
import { Controller, Get, Inject } from '@nestjs/common';
import { AppService } from './app.service';
import { ClientProxy } from '@nestjs/microservices';
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
// Inject中的参数必须对应注册子服务的名称
@Inject('microservice1') private client:ClientProxy,
@Inject('microservice2') private client1:ClientProxy,
) { }
@Get()
getMainService(): string {
console.log('直接使用主服务!')
return this.appService.getHello();
}
// 使用request/response请求响应的方式调用微服务1
@Get('/microservice1')
getMicroservice1Service(): any{
console.log('调用微服务1!')
return this.client.send('math:wordcount', '');
}
// 使用事件触发的方式调用微服务2
@Get('/microservice2')
getMicroservice2Emit(): any{
console.log('调用微服务2!')
this.client1.emit('user_created', 'admin');
return '调用子服务2成功!'
}
}
在子服务中接收主服务的分发
// 子服务1的app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@MessagePattern('math:wordcount')
wordCount(s: string): string {
console.log('子服务1调用成功')
return '这是子服务1!';
}
}
// 子服务2的app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { EventPattern, MessagePattern } from '@nestjs/microservices';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) { }
@EventPattern('user_created')
async handleUserCreated(data: Record<string, unknown>) {
console.log('子服务2事件调用成功',data);
// 这里返回值主服务其实是接收不到的,因为事件触发是不会返回的,只需要确保子服务触发了事件
return ''
}
}
现在只需要进入到每个服务中运行 pnpm start:dev 启动三个服务就大功告成了!!!
使用浏览器访问:
打印 hello world
http://127.0.0.1:3000/microservice1
打印 这是子服务1!
http://127.0.0.1:3000/microservice2
打印 调用子服务2成功!
现在为了让项目的开发体验更好,配置pnpm共享依赖,以及一键启动三个服务
进入项目的根路径中(nest-cloud目录下)创建 pnpm-workspace.yaml 文件
package:
# main-service主服务
- 'main-service'
# children-service下面的所有子服务
- 'children-service/**'
并使用 pnpm init 创建package.json文件
进入到所有服务中删除node_modules依赖文件
再回到项目根目录运行 pnpm i 安装依赖,此时你会发现所有的项目依赖都已经安装上
并且三个服务共有的依赖被抽离到根目录的node_modules中了(项目的文件大小缩小到原来的1/3)!!!
最后还需要配置一键启动命令
先全局安装 npm i -g npm-run-all
{
"name": "nest-cloud",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start:main": "pnpm -F main-service start:dev",
"start:microservice1": "pnpm -F microservice1 start:dev",
"start:microservice2": "pnpm -F microservice2 start:dev",
"start": "npm-run-all --parallel start:main start:microservice1 start:microservice2"
},
"keywords": [],
"author": "",
"license": "ISC"
}
注意:
"start:main": "pnpm -F main-service start:dev",
"start:microservice1": "pnpm -F microservice1 start:dev",
"start:microservice2": "pnpm -F microservice2 start:dev",
中的microservice1,microservice2,main-service对应的是每个服务中package.json的name,
如果是严格按照我上述的步骤进行的话应该名称是不会有问题的,如果不能启动成功,请检查每个package.json文件中的name
所有配置完成之后运行 pnpm start
三个服务就会一并启动!!!