You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cloud Function迁移Cloud Storage大量文件时遇TLS连接断开错误求助

问题描述

将文件迁移至Cloud Storage时,测试5个文件可正常完成,但处理50个以上文件时,函数返回错误:

Exception from a finished function: FetchError: request to https://storage.googleapis.com/storage/v1/b/...-933ca.appspot.com/o?prefix=documents%123123123231321sadas failed, reason: Client network socket disconnected before secure TLS connection was established

Cloud Function代码如下:

exports.updateStorage = functions.https.onRequest(async (req, res) => {
  try {
    await updateStorageData();

    res.send(200);
  } catch (error) {
    console.error('Error updating storage data', error);
    return error;
  }
});


const updateStorageData = async () => {
  const db = admin.firestore();

  db.collection('users')
    .get()
    .then(userSnapshot => {
      userSnapshot.forEach(user => {
        const userId = user.id;

        const subCollectionRef = db
          .collection('users')
          .doc(userId)
          .collection('documents');
        subCollectionRef
          .get()
          .then(snapshot => {
            snapshot.forEach(async doc => {
              await readFiles({ docId: doc.id, userId });
            });
          })
          .catch(err => {
            console.log('Error getting documents', err);
          });
      });
    });
};

async function readFiles({ docId, userId }) {
  const [files] = await admin
    .storage()
    .bucket()
    .getFiles({ prefix: `documents/${docId}` });

  if (files.length === 0) {
    return;
  }

  const promises = [];

  files.forEach(file => {
    promises.push(file.copy(`users/${userId}/${file.name}`));
  });

  await Promise.all(promises);
}

函数详情:

  • First gen函数
  • onRequest触发器
  • 内存配置8GB
  • 通过Firebase控制台的“Testing”标签页运行测试
  • 需访问Firebase Firestore获取数据,并更新Cloud Storage中的文件结构
解决方案

1. 修复异步流程控制漏洞

当前代码的核心问题是异步流程失控,导致函数提前终止、请求被中断:

  • updateStorageData内部使用.then()但未返回Promise,await updateStorageData()会直接执行完成,函数提前结束,后续文件复制请求被强制中断,引发TLS连接错误。
  • forEach中使用async/await无效,forEach不会等待异步函数执行,导致大量请求被同时触发,超出系统连接上限。

修改后的updateStorageData统一用async/await管理异步流程,收集所有Promise等待完成:

const updateStorageData = async () => {
  const db = admin.firestore();
  const userSnapshot = await db.collection('users').get();
  
  // 收集所有用户处理任务
  const userTasks = userSnapshot.docs.map(async user => {
    const userId = user.id;
    const docSnapshot = await db.collection('users').doc(userId).collection('documents').get();
    
    // 收集当前用户下所有文档的处理任务
    const docTasks = docSnapshot.docs.map(doc => readFiles({ docId: doc.id, userId }));
    await Promise.all(docTasks);
  });
  
  await Promise.all(userTasks);
};

2. 限制并发请求数量

一次性触发大量文件复制会导致网络过载,可在readFiles中分批处理,控制并发数:

async function readFiles({ docId, userId }) {
  const [files] = await admin.storage().bucket().getFiles({ prefix: `documents/${docId}` });

  if (files.length === 0) {
    return;
  }

  const batchSize = 10; // 可根据实际情况调整
  // 分批执行文件复制
  for (let i = 0; i < files.length; i += batchSize) {
    const batch = files.slice(i, i + batchSize);
    const copyTasks = batch.map(file => file.copy(`users/${userId}/${file.name}`));
    await Promise.all(copyTasks);
  }
}

3. 调整函数超时时间

First gen Cloud Function默认超时1分钟,处理大量文件时时间不足。可在函数配置中将超时时间调整至最大9分钟(First gen上限)。

4. 优化网络与配额

  • 确保Cloud Function所在区域与Cloud Storage桶区域一致,减少跨区域网络延迟。
  • 检查Cloud Storage的请求配额,若达到每秒请求数限制,可申请配额提升。

内容的提问来源于stack exchange,提问作者Mark James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 21:27:10