微服务中处理Http Exception避免Nestjs应用崩溃方案咨询
在NestJS微服务中处理Http Exception避免应用崩溃的方案
问题原因
NestJS微服务(尤其是RabbitMQ RPC模式)默认只会自动处理RpcException——这是框架为微服务场景设计的异常类型,不会引发应用崩溃。而HttpException是为HTTP服务设计的,微服务运行时没有对应的异常处理逻辑,未捕获的HttpException会直接导致进程崩溃。
方案1:全局异常过滤器(快速解决现有问题)
创建全局异常过滤器,捕获所有未处理的异常,将HttpException转换为RpcException,同时统一处理其他异常。
1.1 实现全局过滤器
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'; import { RpcException } from '@nestjs/microservices'; @Catch() export class GlobalRpcExceptionFilter implements ExceptionFilter { catch(exception: unknown, host: ArgumentsHost) { const ctx = host.switchToRpc(); // 处理HttpException,转换为RpcException if (exception instanceof HttpException) { const status = exception.getStatus(); const response = exception.getResponse(); throw new RpcException({ statusCode: status, message: typeof response === 'string' ? response : (response as any).message, error: (response as any).error || 'Http Exception', }); } // 其他异常统一封装为500级RpcException throw new RpcException({ statusCode: 500, message: 'Internal server error', }); } }
1.2 在微服务中注册全局过滤器
在用户服务的main.ts中注册该过滤器:
import { NestFactory } from '@nestjs/core'; import { UserModule } from './user.module'; import { GlobalRpcExceptionFilter } from './filters/global-rpc-exception.filter'; import { Transport } from '@nestjs/microservices'; async function bootstrap() { const app = await NestFactory.createMicroservice(UserModule, { transport: Transport.RMQ, options: { urls: ['amqp://localhost:5672'], queue: 'user_queue', queueOptions: { durable: false }, }, }); // 注册全局异常过滤器 app.useGlobalFilters(new GlobalRpcExceptionFilter()); await app.listen(); } bootstrap();
可选:局部过滤器
如果不需要全局生效,也可以在控制器或方法级别使用@UseFilters装饰器:
import { Controller, UseFilters } from '@nestjs/common'; import { MessagePattern } from '@nestjs/microservices'; import { GlobalRpcExceptionFilter } from './filters/global-rpc-exception.filter'; @Controller() @UseFilters(GlobalRpcExceptionFilter) export class UserController { @MessagePattern({ cmd: 'get_user' }) async getUser(payload: any) { // 此处抛出的HttpException会被过滤器捕获转换 throw new HttpException('User not found', 404); } }
方案2:规范微服务异常抛出(长期更优方案)
既然是微服务场景,建议直接使用RpcException或自定义Rpc异常,从根源避免HttpException的出现,代码更符合微服务设计逻辑。
2.1 自定义业务Rpc异常
import { RpcException } from '@nestjs/microservices'; export class UserNotFoundException extends RpcException { constructor() { super({ statusCode: 404, message: 'User not found' }); } } // 其他业务异常示例 export class InvalidCredentialsException extends RpcException { constructor() { super({ statusCode: 401, message: 'Invalid credentials' }); } }
2.2 在服务中使用自定义异常
import { Injectable } from '@nestjs/common'; import { UserNotFoundException } from './exceptions/user-not-found.exception'; @Injectable() export class UserService { async getUserById(id: string) { const user = await this.userRepository.findOneBy({ id }); if (!user) { throw new UserNotFoundException(); } return user; } }
额外建议
- 用管道做输入验证:在接收RPC请求时,使用管道验证参数合法性,提前抛出
RpcException,避免后续业务逻辑中出现异常。 - 日志记录:在异常过滤器中加入日志逻辑,记录异常详情,便于排查问题。
内容的提问来源于stack exchange,提问作者morteza mortezaie
相关产品推荐
相关产品推荐

