[英]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.