[英]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);
}
}
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('...')
}
}
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.