You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

微服务中处理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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 05:00:31