dav*_*ui6 3 grpc nestjs nestjs-gateways
我正在尝试构建一个包含多个微服务的 NestJS 后端和一个作为与微服务通信的网关的 REST API。对于网关和微服务之间的通信,我使用 gRPC。简单的通信已经可以工作,但现在我想在微服务中实现错误处理。NestJS 文档指出,这可以通过 RpcException 类实现。https://docs.nestjs.com/microservices/exception-filters但是,如果我尝试捕获网关 API 中的异常,我只会收到“ERROR [ExceptionsHandler] 2 UNKNOWN:...”,然后是异常错误消息。
网关API:user.controller.ts
import { Controller, Get, Param } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { UserViewModel } from '../../proto/build/service-name/user';
import { UserService } from './user.service';
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {}
@Get(':id')
async getUserById(@Param('id') id: number): Promise<UserViewModel> {
try {
return await this.userService.getUserById(id);
} catch (error) {
return error;
}
}
}
Run Code Online (Sandbox Code Playgroud)
网关API:user.service.ts
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import {
IUserService,
UserViewModel,
} from '../../proto/build/service-name/user';
@Injectable()
export class UserService implements OnModuleInit {
private grpcService: IUserService;
constructor(@Inject('USER_PACKAGE') private client: ClientGrpc) {}
onModuleInit() {
this.grpcService = this.client.getService<IUserService>('IUserService');
}
async getUserById(id: number): Promise<UserViewModel> {
return this.grpcService.getUserById({ id });
}
}
Run Code Online (Sandbox Code Playgroud)
微服务:user.controller.ts
import { Metadata } from '@grpc/grpc-js';
import { Controller } from '@nestjs/common';
import { GrpcMethod, RpcException } from '@nestjs/microservices';
import { User } from './../../node_modules/.prisma/client/index.d';
import { PrismaService } from '../prisma/prisma.service';
import { UserViewModel, GetUserById } from '../proto/build/service-name/user';
@Controller()
export class UserController {
constructor(private readonly prisma: PrismaService) {}
@GrpcMethod('IUserService', 'getUserById')
async getUserById(
data: GetUserById,
metadata: Metadata,
): Promise<UserViewModel> {
const user: User = await this.prisma.user.findFirst({
where: { id: { equals: data.id } },
});
if (!user) {
throw new RpcException('User not found');
}
return { name: user.name, email: user.email };
}
}
Run Code Online (Sandbox Code Playgroud)
我在使用 API 网关构建微服务时也遇到了这个问题。我提出的解决方案是我在这里找到的答案的组合,但允许您使用 NestJS 异常中的构建。
所以基本上我将内置的 NestJS HTTP 异常包装RpcException在微服务中。然后,您可以捕获 api 网关中的执行并使用过滤器处理它。该RcpException消息可以是 astring或object,这允许您将内置的 HTTP 异常( 、 等)作为消息传递NotFoundException,UnauthorizedException这样您就不必处理状态代码。
// Some service method to fetch a product by id
public async findById(id: number): Promise<Product> {
// ...
if (!product) {
throw new RpcException(
new NotFoundException("Product was not found!");
);
}
//...
}
Run Code Online (Sandbox Code Playgroud)
@Get(':productId')
public getProductById(@Param('productId') productId: number): Observable<any> {
return this._productsServiceClient
.send({ cmd: 'find-by-id' }, { productId })
.pipe(catchError(error => throwError(() => new RpcException(error.response))))
}
Run Code Online (Sandbox Code Playgroud)
import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common';
import { RpcException } from '@nestjs/microservices';
import { Response } from 'express';
@Catch(RpcException)
export class RpcExceptionFilter implements ExceptionFilter {
catch(exception: RpcException, host: ArgumentsHost) {
const error: any = exception.getError();
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
response
.status(error.statusCode)
.json(error);
}
}
Run Code Online (Sandbox Code Playgroud)
// main.ts
app.useGlobalFilters(new RpcExceptionFilter());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8884 次 |
| 最近记录: |