由于错误处理承诺而导致的套接字挂断

Posted

技术标签:

【中文标题】由于错误处理承诺而导致的套接字挂断【英文标题】:Socket hangup due to wrong handling of promises 【发布时间】:2021-11-13 14:08:56 【问题描述】:

我有脚本可以将数据从一个平台移动到另一个平台。源数据库只允许在单个请求中获取 100 条记录。所以我创建了一个例程来批量获取 100 个,我猜它工作正常。

现在我尝试处理每条 100 条记录并进行必要的转换(这涉及到 axios 调用以获取某些数据)并在 firebase firestore 中创建一条记录。 现在,当我在 firebase express 节点中运行此迁移时,我的套接字挂断了 ECONNRESET。

我知道这是由于对 promise 的错误处理造成的。

我的代码如下所示:


import  scrollByBatches  from "../helpers/migrations/apiScroll";
import  createServiceLocation  from "../helpers/locations";

const mapServiceLocationData = async (serviceLocation: any, env: string) => 
  try 
    const migratedServiceLocation: any = 
      isMigrated: true,
      id: serviceLocation._id,
    ;


    if (serviceLocation.list?.length) 
      await Promise.all(serviceLocation.ids.map(async (id: string) => 
        const  data  = await dbEndPoint.priceMultiplier( id );  // error says socket hangup on this call
        let multiplierUnit;
        let serviceType;
        if (data.response._id) 
          multiplierUnit = data.response;
          const result = await dbEndPoint.serviceType( id: multiplierUnit.service_custom_service_type ); // error says socket hangup on this call
          if (result.data.response._id) 
            serviceType = result.data.response.type_text;
            migratedServiceLocation.logs = [...multiplierUnit.history_list_text, ...migratedServiceLocation.logs];
          
        
      ));
    

    await createServiceLocation(migratedServiceLocation); // create record in destination db
   catch (error) 
    console.log("Error serviceLocation: ", serviceLocation._id, JSON.stringify(error));
  
  return null; // is this even necessary?
;

export const up = async () => 
  try 
    // get 100 docs from source db => process it.. => fetch next 100 => so on...
    await scrollByBatches(dbEndPoint.serviceLocation, async (serviceLocations: any) => 
      await Promise.all(
          serviceLocations.map(async (serviceLocation: any) => 
            await mapServiceLocationData(serviceLocation);
          )
      );
    , 100);
   catch (error) 
    console.log("Error", JSON.stringify(error));
  
  return null; // is this even necessary?
;

我在 firebase 函数控制台中遇到的错误是:

为了清楚分批获取的外观如下:

const iterateInBatches = async (endPoint: any, limit: number, cursor: number, callback: any, resolve: any, reject: any) => 
  try 
    const result = await endPoint( limit, cursor );
    const  results, remaining : any = result.data.response;

    if (remaining >= 0) 
      await callback(results);
    
    if ((remaining)) 
      setTimeout(() => 
        iterateInBatches(endPoint, limit, (cursor + limit), callback, resolve, reject);
      , 1000); // wait a second
     else 
      resolve();
    
   catch (err) 
    reject(err);
  
;

export const scrollByBatches = async (endPoint: any, callback: any, limit: number, cursor: number = 0) => 
  return new Promise((resolve, reject) => 
    iterateInBatches(endPoint, limit, cursor, callback, resolve, reject);
  );
;

我做错了什么?为了便于阅读,我在代码部分添加了 cmets。

谢谢。

【问题讨论】:

嘿VPR。你在这方面有什么进展吗?我试图在下面提供答案。你有没有机会检查一下,这有意义吗?如果我的回答有用,请点击它左侧的点赞按钮 (▲)。如果它回答了您的问题,请单击复选标记 (✓) 接受它。这样其他人就知道你得到了(足够的)帮助。 我离开了。似乎没有任何效果。 我做了一个工作来解决这个任务。而不是计算和处理只在云中失败的承诺,在模拟器中一切正常。所以我所做的就是在模拟器中完成所有工作,并在云中创建一个端点,只是为了创建作为有效负载传递的记录。 【参考方案1】:

socket hang up 有两种情况:

当您是客户时

当您作为客户端向远程服务器发送请求时,没有及时收到响应。您的套接字已结束,这会引发此错误。您应该捕获此错误并决定如何处理它:是否重试请求、将其排队以备后用等。

当您是服务器/代理时

当您作为服务器(可能是代理服务器)收到来自客户端的请求,然后开始对其采取行动(或将请求中继到上游服务器),在您准备好响应之前,客户端决定取消/中止请求。

我建议您尝试和测试一些可能帮助您解决 ECONNRESET 问题的可能性:

如果您可以访问源数据库,您可以尝试查找 那里有一些日志或指标。也许你正在超载 服务。

用于开发的快速而肮脏的解决方案:使用longjohn,你会很长 将包含异步操作的堆栈跟踪。清洁和 正确的解决方案:从技术上讲,在节点中,每当您发出“错误”时 事件并且没有人听它,它会抛出错误。让它 不要扔,在上面放一个监听器并自己处理。这样你 可以用更多信息记录错误。

您也可以设置 NODE_DEBUG=net 或使用strace。他们都为您提供 节点在内部做什么。

您可以重新启动服务器并再次运行连接,也许 您的服务器崩溃或拒绝连接很可能被阻止 用户代理。

您也可以尝试在本地运行此代码,而不是在云端运行 函数来查看是否有不同的结果。有可能是 RSG/google 网络正在以某种方式干扰。

您还可以查看 GitHub issue 和 *** thread 以查看 ECONNRESET 问题的常见修复,看看是否 这些有助于解决问题。

【讨论】:

以上是关于由于错误处理承诺而导致的套接字挂断的主要内容,如果未能解决你的问题,请参考以下文章

错误:使用 https 挂断套接字

多个 API 调用的 Node Js 中的套接字挂断错误

nodejs https错误:套接字挂断了本地主机

mongoose 的重复键错误处理和未处理的承诺拒绝

带有 Gunicorn 的 Flask App 在生产中给出错误:套接字挂断

由于每月收入计算错误导致的问题