为什么SettiMeout在我的服务器(GCP)上不起作用?

发布于 2025-01-23 20:09:45 字数 3560 浏览 0 评论 0原文

我有一个node.js Web应用程序,并且正在进行一个API调用,如果我要求的频率不超过一次,则会导致过载。因此,我必须在每个呼叫之间暂停约1秒的API呼叫。事实证明,这比应该更加困难。

我目前使用以下代码:

var i = 0
db.collection('products').get()
   .then(async (querySnapshot) => {
   var docs = querySnapshot.docs.map(doc => doc);  
 
   docs.forEach(async (doc) => {  
      i += 1
      setTimeout( () => {                     
         console.log(new Date(), "Zzz", i);
         theApiCall().then((locationData) => {
            let result = {
               'location': {
                  'country': result,
               }
            }                                         
         })                   
       }, i * 1500)
   })
})

在我的本地Mac(Apple M1)中使用以下日志输出的A中可以正常工作:

...200 lines of ~1.5 seconds in between and then:
2022-04-23T11:23:51.616Z Zzzz... 957
2022-04-23T11:23:53.117Z Zzzz... 957
2022-04-23T11:23:54.615Z Zzzz... 957
2022-04-23T11:23:56.116Z Zzzz... 957
2022-04-23T11:30:30.245Z Zzzz... 957
2022-04-23T11:30:30.247Z Zzzz... 957
2022-04-23T11:30:30.248Z Zzzz... 957
2022-04-23T11:30:30.250Z Zzzz... 957
node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

Error: 4 DEADLINE_EXCEEDED: Deadline exceeded
    at Object.callErrorFromStatus (/Users/Christoffer/projects/node/apiapplication//node_modules/@grpc/grpc-js/build/src/call.js:31:26)
    at Object.onReceiveStatus (/Users/Christoffer/projects/node/apiapplication//node_modules/@grpc/grpc-js/build/src/client.js:180:52)
    at Object.onReceiveStatus (/Users/Christoffer/projects/node/apiapplication//node_modules/@grpc/grpc-js/build/src/client-interceptors.js:365:141)
    at Object.onReceiveStatus (/Users/Christoffer/projects/node/apiapplication//node_modules/@grpc/grpc-js/build/src/client-interceptors.js:328:181)
    at /Users/Christoffer/projects/node/apiapplication//node_modules/@grpc/grpc-js/build/src/call-stream.js:182:78
    at processTicksAndRejections (node:internal/process/task_queues:78:11)
    at runNextTicks (node:internal/process/task_queues:65:3)
    at processTimers (node:internal/timers:497:9)
Caused by: Error
    at WriteBatch.commit (/Users/Christoffer/projects/node/apiapplication//node_modules/@google-cloud/firestore/build/src/write-batch.js:414:23)
    at DocumentReference.set (/Users/Christoffer/projects/node/apiapplication//node_modules/@google-cloud/firestore/build/src/reference.js:351:14)
    at /Users/Christoffer/projects/node/apiapplication//server.js:1400:120
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  code: 4,
  details: 'Deadline exceeded',
  metadata: Metadata { internalRepr: Map(0) {}, options: {} },
  note: 'Exception occurred in retry method that was not classified as transient'

错误消息本身并不有趣,我认为与API有关因此引发了拒绝(?)。

但是,当我在Cloud Run(Google Cloud Platform)上运行此操作时,它似乎很快就完全忽略了settimeout - 并间歇性地这样做:

2022-04-24T22:01:54.367Z Zzzz... 2966
 2022-04-24T22:01:54.370Z Zzzz... 2966
 2022-04-24T22:01:54.373Z Zzzz... 2966
 2022-04-24T22:01:54.374Z Zzzz... 2966
 2022-04-24T22:01:54.375Z Zzzz... 2966
 2022-04-24T22:01:54.437Z Zzzz... 2966
 2022-04-24T22:01:56.688Z Zzzz... 2966
 2022-04-24T22:01:59.300Z Zzzz... 2966
2022-04-24T22:01:59.302Z Zzzz... 2966
2022-04-24T22:02:00.545Z Zzzz... 2966

为什么Settimeout行为如此奇怪(“不信任” )?我该怎么做才能真正强迫在GCP上工作的停顿?

什么也让我感到非常奇怪的是:为什么i总是957(分别为2966)?这不应该增加(1,2..N)吗?这可能会影响超时分布的方式并导致API拒绝。

I have a Node.js web application and I am doing an API call that will cause an overload if I request it more often than once a second. So, I have to pause the API call with ~1 sec between every call. It proves to be more difficult than it should be.

I currently use this following code:

var i = 0
db.collection('products').get()
   .then(async (querySnapshot) => {
   var docs = querySnapshot.docs.map(doc => doc);  
 
   docs.forEach(async (doc) => {  
      i += 1
      setTimeout( () => {                     
         console.log(new Date(), "Zzz", i);
         theApiCall().then((locationData) => {
            let result = {
               'location': {
                  'country': result,
               }
            }                                         
         })                   
       }, i * 1500)
   })
})

This works fine for a in my local Mac (Apple M1) with the following log output:

...200 lines of ~1.5 seconds in between and then:
2022-04-23T11:23:51.616Z Zzzz... 957
2022-04-23T11:23:53.117Z Zzzz... 957
2022-04-23T11:23:54.615Z Zzzz... 957
2022-04-23T11:23:56.116Z Zzzz... 957
2022-04-23T11:30:30.245Z Zzzz... 957
2022-04-23T11:30:30.247Z Zzzz... 957
2022-04-23T11:30:30.248Z Zzzz... 957
2022-04-23T11:30:30.250Z Zzzz... 957
node:internal/process/promises:246
          triggerUncaughtException(err, true /* fromPromise */);
          ^

Error: 4 DEADLINE_EXCEEDED: Deadline exceeded
    at Object.callErrorFromStatus (/Users/Christoffer/projects/node/apiapplication//node_modules/@grpc/grpc-js/build/src/call.js:31:26)
    at Object.onReceiveStatus (/Users/Christoffer/projects/node/apiapplication//node_modules/@grpc/grpc-js/build/src/client.js:180:52)
    at Object.onReceiveStatus (/Users/Christoffer/projects/node/apiapplication//node_modules/@grpc/grpc-js/build/src/client-interceptors.js:365:141)
    at Object.onReceiveStatus (/Users/Christoffer/projects/node/apiapplication//node_modules/@grpc/grpc-js/build/src/client-interceptors.js:328:181)
    at /Users/Christoffer/projects/node/apiapplication//node_modules/@grpc/grpc-js/build/src/call-stream.js:182:78
    at processTicksAndRejections (node:internal/process/task_queues:78:11)
    at runNextTicks (node:internal/process/task_queues:65:3)
    at processTimers (node:internal/timers:497:9)
Caused by: Error
    at WriteBatch.commit (/Users/Christoffer/projects/node/apiapplication//node_modules/@google-cloud/firestore/build/src/write-batch.js:414:23)
    at DocumentReference.set (/Users/Christoffer/projects/node/apiapplication//node_modules/@google-cloud/firestore/build/src/reference.js:351:14)
    at /Users/Christoffer/projects/node/apiapplication//server.js:1400:120
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  code: 4,
  details: 'Deadline exceeded',
  metadata: Metadata { internalRepr: Map(0) {}, options: {} },
  note: 'Exception occurred in retry method that was not classified as transient'

The error message in itself is not so interesting as I believe it has to do with the API getting too many calls and thus throws a rejection (?).

However, when I run this at Cloud Run (Google Cloud Platform), it quickly seems to completely ignore the setTimeout - and does so intermittently:

2022-04-24T22:01:54.367Z Zzzz... 2966
 2022-04-24T22:01:54.370Z Zzzz... 2966
 2022-04-24T22:01:54.373Z Zzzz... 2966
 2022-04-24T22:01:54.374Z Zzzz... 2966
 2022-04-24T22:01:54.375Z Zzzz... 2966
 2022-04-24T22:01:54.437Z Zzzz... 2966
 2022-04-24T22:01:56.688Z Zzzz... 2966
 2022-04-24T22:01:59.300Z Zzzz... 2966
2022-04-24T22:01:59.302Z Zzzz... 2966
2022-04-24T22:02:00.545Z Zzzz... 2966

Why is the setTimeout behaving so odd ("untrustworthy")? What can I do to really force a pause here that will work on GCP as well?

What strikes me as very odd as well is: Why is i always 957 (2966 respectively)? Shouldn't this be incremented (1,2..n)? This could possibly affect how the timeouts are being spread out and cause the API rejection.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文