NestJS小技巧27-掌握API性能:使用NestJS构建超时拦截器

1,006 阅读5分钟
by 雪隐 from https://juejin.cn/user/1433418895994094
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可联系授权

原文链接

在现代web开发中,创建一个可靠的和可响应API对用户的体验是至关重要的。然而,API有时候会遭遇问题然而导致进程处理时间延长,这会影响您的整个应用性能。为了克服这个挑战,实现一个超时拦截器是非常有必要的。在这篇文章中,我将会使用NestJS来探索超时拦截器的实现。这篇文章不会解释和说明NestJS,但是如果您对NestJS的基础还不太了解,可以先看看官方的文档

想象一个情景,您的应用程序正在和多个服务或者资源进行交互。如果这些资源中的某个资源变得没有响应或者响应延迟,这将会导致您的API请求不停的等待。但是这些不是必须的资源并且使您的用户产生不满。所以非常有必要来实现一个装置能够在API请求的时候,如果响应数据没有在特定的时间内返回,这个请求将会被优雅的终止并返回一个合适异常。

考虑一个与各种支付网关集成以处理交易的电子商务平台。当处理一个支付的时候,您的应用程序和支付网关进行交互。然而,如果这个支付网关发生API延迟或者网络中断,它可能会在很长一段时间内阻止您的API请求,影响应用程序的其他部分,并导致其他用户的延迟。通过实现一个超时拦截器,这个支付网关在预期的时间内没有响应的话,您能终止这个请求并且返回一个异常消息给客户端,使您的应用程序能够优雅的处理诸如此类的情况。

使用超时拦截器的优点:

在NestJS中实现一个超时拦截器有许多好处并能使您的API变得牢固且可响应。

1. 资源管理: 长时间运行或停滞的API请求可能会占用服务器资源,导致潜在的性能下降和可扩展性降低。超时拦截器通过终止超过预定义时间阈值的请求来帮助防止资源耗尽。

2. 提高用户体验: 通过为API请求设定一个合理的超时机制,您能确认用户不会被一些外部服务无响应情况而产生延迟的体验。这能提升所有用户的体验并把您的应用程序描绘的可靠且有响应。

3. 故障快速原则: 拦截器遵循故障快速原则,这意味着他能快速的辨认并处理问题。如果API长时间等待似乎异常,最好把它终止并返回一个合理的异常消息。

4. 关注点分离: 超时拦截器从单独的API端点中抽象出了超时逻辑,促使代码更加整洁和可维护。关注点分离可以使得开发者将注意力集中在端点的业务核心上,不用担心超时的问题。

5. 优雅的处理异常: 与其让请求不停的等待或者应用程序崩溃,不如让拦截器捕获这个超时异常并且转化为有意义的例外。这能够让您优雅的处理异常并给客户端提供清楚的异常信息


超时拦截器的实现:

以下是在NestJS中的一个超时拦截器的实现

import { CallHandler, ExecutionContext, GatewayTimeoutException, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable, TimeoutError, throwError } from 'rxjs';
import { catchError, timeout } from 'rxjs/operators';

@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
  constructor(private readonly timeoutInMillis: number) { }

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      timeout(this.timeoutInMillis),
      catchError((err) => {
        if (err instanceof TimeoutError) {
          throw new GatewayTimeoutException('Gateway timeout has occurred');
        }
        return throwError(() => err);
      }),
    );
  }
}

在这个实现中,拦截器从构造器参数中获得一个timeout值。然后,使用rxjs库中的timeout给他设定这个值并拦截进来的请求。如果请求超过这个特定的时间,一个TimeoutError会被捕获,并且 指向超时的GatewayTimeoutExcepiton异常会抛出到客户端。

为了传递timeout值给这个拦截器的构造函数,我们通过ConfigService读取这个配置信息并把它按照下面的方法传递给拦截器构造函数,您可以创建一个.env文件并添加您设计好的超时时间,如果不存在相同的情况,则默认超时将设置为30秒。

TIMEOUT_IN_MILLISECONDS=<YOUR_DESIRED_TIMEOUT>
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';;
import { APP_INTERCEPTOR } from '@nestjs/core';
import { TimeoutInterceptor } from './interceptors/timeout.interceptor';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
  ],
  controllers: [],
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useFactory: (configService: ConfigService) => {
        const timeoutInMilliseconds: number = parseInt(configService.get<any>('TIMEOUT_IN_MILLISECONDS', 30000));
        return new TimeoutInterceptor(timeoutInMilliseconds);
      },
      inject: [ConfigService],
    }
  ],
})
export class AppModule { }

在web开发的世界里,确保有响应且可靠的API是首要任务。在NestJS中实现一个超时拦截器使您能够有效的管理API请求,防止资源浪费,提供更好的用户体验。通过解偶超时逻辑,您能够优雅的处理异常并且确保您的应用程序即使在与外部服务交互时也保持健壮。将超时拦截器集成到NestJS应用程序中,表明您致力于提供可靠且用户友好的高质量服务。

本章代码

代码