簡體   English   中英

如何在 node.js 中運行 api 請求 6/8 小時或更長時間?

[英]How to run an api request for 6/8 hours or more in node js?

我必須通過 api2cart API 從 shopify 提取大量數據。我需要提取 2/3 年前的數據,這需要幾個小時才能提取,因為我們每個請求只能提取 250 個項目。 對於每個響應,它都會提供下一個 250 數據拉取的密鑰,依此類推。

在我的后端,我正在提取數據並通過 fs 將其保存在 csv 文件中,然后我再次調用 api 以獲取接下來的 250 個項目。 它在我的本地機器上運行良好。 該過程一直持續到獲取所有數據為止。 我可以提取多年的數據,提取大約 100k/150k 數據大約需要 2-3 小時。

然后我設置了一個 NestJS 微服務並部署在數字海洋服務器上。 但是當我長時間發出 API 請求時,一段時間后,服務器給我一個 504 網關超時錯誤。

不能使用 setTimeout,因為這個過程沒有限制。 有什么辦法可以持續數小時或數天提取數據?

如何在沒有任何 504 網關超時錯誤的情況下提取數小時的數據?

運行時間非常長的請求通常容易出錯。 連接重置可能會導致再次重新啟動整個過程。 盡管這不能解決您描述的數字海洋的底層問題,但我認為您值得考慮一個不同的解決方案。 我建議將繁重的、長時間運行的任務拆分成許多小任務,並使用隊列系統。

Nestjs 提供了一個非常好的文檔使用隊列和公牛 package。

我添加了一個基本示例,有兩個解決方案:

隊列消費者

shopify.consumer.ts

import { Processor, Process } from '@nestjs/bull';
import { Job } from 'bull';

@Processor('shopify')
export class ShopifyConsumer {
  constructor(
    private shopifyService: ShopifyService
  ) {}

  @Process('fetch')
  async transcode(job: Job<unknown>) {
    await this.shopifyService.fetch(job.requestKey);
  }
}

選項 a) 一次生成所有請求並讓隊列處理它們:

shopify.service.ts

import { Injectable } from '@nestjs/common';
import { Queue } from 'bull';
import { InjectQueue } from '@nestjs/bull';

@Injectable()
export class ShopifyService {
  constructor(
    @InjectQueue('shopify') private shopifyQueue: Queue
  ) {}
    
  generateJobs(requestKeys: string[]) {
    for (const requestKey of requestKeys) {
      await this.shopifyQueue.add('fetch', { 
        requestKey
      });
    }
  }

  fetch(requestKey: string) {
    // Fetch data
    const res = await fetch('...')
  }
}

選項 b) 在每次響應后生成一個新的隊列作業

shopify.service.ts

import { Injectable } from '@nestjs/common';
import { Queue } from 'bull';
import { InjectQueue } from '@nestjs/bull';

@Injectable()
export class ShopifyService {
  constructor(
    @InjectQueue('shopify') private shopifyQueue: Queue
  ) {}

  fetch(requestKey: string) {
    // Fetch data
    const res = await fetch('...')
    
    // Add next job to queue if more chunks are available
    if (res.nextRequestKey) {
      await this.shopifyQueue.add('fetch', { 
        requestKey: res.nextRequestKey
      })
    }
  }
}

Queues 和 Bull 與 NestJS 配合得很好,我會推薦它們用於這些長調用。 這真的很有幫助,因為您還可以重試呼叫,並為失敗的作業添加超時(以幫助解決 417 錯誤)。

import { Injectable } from '@nestjs/common';
import { Queue } from 'bull';
import { InjectQueue } from '@nestjs/bull';

@Injectable()
export class ShopifyService {
  constructor(
    @InjectQueue('shopify') private shopifyQueue: Queue
  ) {}
    
  async generateJobs(requestKeys: string[]) {

    await this.shopifyQueue.addBulk('${QUEUE_NAME}.${JOB_NAME}', { 
      ...jobData //what is needed to make API call
    },
    {
      attempts: 5,
      backoff: 5000,
      //Will try 5 times with backoff
    });
  }
}
    ```

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM