添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

重试http请求并进行回退 - (Nestjs - axios - rxjs) 抛出套接字挂起

0 人关注

[second-Update]: 我通过使用承诺和try & catch来解决了这个问题

[第一次更新]。 我试着用HTTP请求的重试机制, content-type: application/json ,它工作了!!但我的问题是内容类型 form-data 。 我想这和这个问题很相似: Axios拦截器重试发送FormData

我试图从NestJS-app向服务a发出一个HTTP请求。 而且我想用回退逻辑实现重试。 为了重现服务a的失败,我重新启动了它的docker容器并发出了HTTP请求。 重试逻辑实现为3次重试。 第一次重启时,service-a被抛出 405 service not available 错误,并进行重试。 所有3次重试都失败了,出现了 socket hang up 的错误。

使用axios nestjs wrapper lib的HTTP请求代码 retryWithBackOff rxjs 操作符的实现

第一次调用抛出一个 405 Service Unavailable 错误。 然后应用程序开始重试。 service-a 开始后第一次重试,失败了,有错误。 socket hang up 第一次、第二次和第三次重试失败, socket hang up 3个套接字挂起了错误

我的预期行为是。 当 service-a 开始后,第一次重试就开始了,它应该能成功响应。

请注意,3次重试并没有向Nginx服务器记录任何信息!

node.js
http
axios
nestjs
Ahmed Atef
Ahmed Atef
发布于 2021-08-08
1 个回答
PixelBucket
PixelBucket
发布于 2021-08-09
0 人赞同

虽然你的解决方案可能是有效的,但它可以在单一责任方面进行改进,这一点RxJS可以提供帮助。我使用的是我曾经在网上找到的一个代码片段的改编方案(我已经找不到原始来源了)。

interface GenericRetryStrategy {
  getAttempt?(): number;
  maxRetryAttempts?: number;
  scalingDuration?: number;
  maxDuration?: number;
  retryFormula?: RetryFormula;
  excludedStatusCodes?: number[]; // All errors with these codes will circumvent retry and just return the error
const genericRetryStrategy$ =
    getAttempt,
    maxRetryAttempts = 3,
    scalingDuration = 1000,
    maxDuration = 64000,
    retryFormula = 'constant', // time-to-retry-count interpolation
    excludedStatusCodes = [], // All errors with these codes will circumvent retry and just return the error
  }: GenericRetryStrategy = {}) =>
  (error$: Observable<unknown>): Observable<number> =>
    error$.pipe(
      switchMap((error, i) => {
        const retryAttempt = getAttempt ? getAttempt() : i + 1;
        // if maximum number of retries have been met
        // or response is a error code we don't wish to retry, throw error
          retryAttempt > maxRetryAttempts ||
          excludedStatusCodes.find(e => e === error.code)
          return throwError(error);
        const retryDuration = getRetryCurve(retryFormula, retryAttempt);
        const waitDuration = Math.min(
          maxDuration,
          retryDuration * scalingDuration,
        // retry after 1000ms, 2000ms, etc …
        return timer(waitDuration);

然后你会这样调用它。

const retryThreeTimes$ = genericRetryStrategy$({
      maxRetryAttempts: 3,
      excludedStatusCodes: [HttpStatus.PayloadTooLarge, HttpStatus.NotFound] // This will throw the error straight away