网关微服务的角色
网关(Gateway)微服务是整个微服务架构的统一入口。客户端(Web、小程序等)不直接调用各个微服务,而是通过网关进行请求转发。网关负责:
- 统一路由和请求分发
- 认证鉴权
- 限流熔断
- 协议转换(HTTP → gRPC)
创建网关项目
从微服务模板项目复制一份,重命名为 gateway:
cp -r template gateway
cd gateway
pnpm install
bash
网关是一个普通的 NestJS HTTP 服务,同时作为 gRPC 客户端调用其他微服务。
配置 gRPC 客户端
在网关的模块中注册 gRPC 客户端,连接到用户微服务:
// src/app.module.ts
import { Module } from '@nestjs/common'
import { ClientsModule, Transport } from '@nestjs/microservices'
import { join } from 'path'
@Module({
imports: [
ClientsModule.register([
{
name: 'USER_SERVICE',
transport: Transport.GRPC,
options: {
package: 'user',
protoPath: join(__dirname, '../proto/user.proto'),
url: 'localhost:5000' // 用户微服务地址
}
}
])
],
controllers: [AppController]
})
export class AppModule {}
typescript
实现登录接口
将原有 monolith 项目中的 Auth 模块迁移到网关中。核心逻辑不变,只是数据访问从直接调用数据库变为通过 gRPC 调用用户微服务。
// src/auth/auth.controller.ts
import { Controller, Post, Body, Inject } from '@nestjs/common'
import { ClientGrpc } from '@nestjs/microservices'
interface UserService {
findOne(data: { username: string }): Observable<any>
create(data: any): Observable<any>
}
@Controller('auth')
export class AuthController {
private userService: UserService
constructor(
@Inject('USER_SERVICE') private client: ClientGrpc
) {}
onModuleInit() {
this.userService = this.client.getService<UserService>('UserService')
}
@Post('login')
async login(@Body() body: { username: string; password: string }) {
const user = await this.userService
.findOne({ username: body.username })
.toPromise()
// 验证密码、生成 Token 等逻辑...
return { token: 'generated-jwt-token', user }
}
@Post('register')
async register(@Body() body: { username: string; password: string }) {
const result = await this.userService
.create({ username: body.username, password: body.password })
.toPromise()
return result
}
}
typescript
依赖迁移清单
从原有项目中迁移 Auth 模块时,需要同步安装以下依赖:
# 参数校验
pnpm add class-validator class-transformer
# JWT 认证
pnpm add @nestjs/jwt @nestjs/passport passport passport-local passport-jwt
# 装饰器
# 从原项目复制 src/common/decorators/ 目录
bash
同时需要在 main.ts 中启用全局验证管道:
app.useGlobalPipes(new ValidationPipe({ transform: true }))
typescript
测试
启动用户微服务和网关服务后,通过 HTTP 请求测试:
# 注册
curl -X POST http://localhost:3000/auth/register \
-H "Content-Type: application/json" \
-d '{"username": "test", "password": "123456"}'
# 登录
curl -X POST http://localhost:3000/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "test", "password": "123456"}'
bash
网关收到 HTTP 请求后,通过 gRPC 调用用户微服务的 findOne 和 create 方法,再将结果转换为 HTTP 响应返回给客户端。
↑